我正在使用牛津字典API设计个人字典应用程序。我试图在单击搜索按钮或在建议单词列表中单击单词后显示该单词的完整页面视图。但单击列表中的单词或搜索按钮后,出现“无法读取未定义的属性”路径名”的错误。另外,整个页面的浏览量也不会显示
我已经在搜索框组件中编写了两个名为btnClick()
和onListClick()
的函数来实现此目的。这已在相应的HTML文件中处理。另外,我有一个名为fullview的组件,它提供了单词的完整视图。
search-box.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormControl } from '@angular/forms';
import { WordService } from '../word.service';
import { ToastrService } from 'ngx-toastr';
import { filter , switchMap } from 'rxjs/operators';
@Component({
selector: 'app-search-box',
templateUrl: './search-box.component.html',
styleUrls: ['./search-box.component.css']
})
export class SearchBoxComponent implements OnInit {
public searchField : FormControl = new FormControl();
public wordList:any;
public displayList = false;
public link;
constructor(private router:Router, private http:WordService, private toastr:ToastrService) { }
ngOnInit() {
this.searchField.valueChanges
.pipe(
filter(value => !value || value.length > 2 || value !== ''),
filter(value => value !== ''),
switchMap( query => query.length > 2 ? this.http.getWord(query) : this.wordList = ' ')
)
// handling observable
.subscribe(
data => {
this.wordList = '';
this.displayList = true;
this.wordList = data;
},
// handling http error codes
error => {
console.log(error);
if(error.status === 404 || error.status === 414){
this.toastr.error('Try again with valid word');
}
else if(error.status === 403){
this.toastr.error(`Invalid credentials`,`Please enter correct details`);
}
else if(error.status === 414){
this.toastr.error(`Your word is too long`,`Please reduce the length of the word`);
}
else if(error.status === 500){
this.toastr.warning(`Something is broken`,`Please contact developer`);
}
else if(error.status === 502){
this.toastr.info(`Oxford Dictionaries API is down or being upgraded`,`Bad Gateway`);
}
else if(error.status === 503){
this.toastr.info(`Please try again later`, `Service Unavailable`);
}
else if(error.status === 504){
this.toastr.info(`Please try again later`, `Gateway timeout`);
}
}
);
}
// declared focus function for search box value
public onFocus(value)
{
if(value.length > 0)
{
this.displayList = true;
}
else
{
this.displayList = false;
}
}
// declared onListClick function for clicking word in list
public onListClick(e)
{
this.link = this.router.url.split('/');
if (this.link.indexOf('definition') > -1) {
this.displayList = false;
}
e.stopPropagation();
this.router.navigate([e.target.children['0'].pathname]); // error in this line
}
//declared button click function
public btnClick(value)
{
const letters = /^[A-Za-z ]*$/;
const regexp = value.match(letters);
if(regexp === null || value === '')
{
alert('Please enter a word');
}
else
{
this.router.navigate(['/definition',value]);
}
}
}
search-box.component.html
<div class="form-inline m-auto flex-center input-group">
<input #searchBox [formControl]="searchField" type="search" class="form-control" placeholder="Enter More than 3 Characters"
(focus)="onFocus(searchBox.value)" required>
<div class="input-group-append">
<button (click)="btnClick(searchBox.value)" class="btn-rounded btn-md btn-mdb-color m-0" type="button"
>Search
<i class="fa fa-search" aria-hidden="true"></i>
</button>
</div>
<div *ngIf="displayList">
<ul class="autocomplete-wrap mt-3" *ngIf="wordList">
<li *ngFor="let word of wordList.results " (click)="onListClick($event)">
<a [routerLink]="['/definition', word.id]">
{{word.word}}
</a>
</li>
</ul>
</div>
</div>
full-view.component.ts
import { Component, OnInit } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { Router, ActivatedRoute } from '@angular/router';
import { WordService } from '../word.service';
import { unionBy, uniq, sortBy } from 'lodash-es';
@Component({
selector: 'app-full-view',
templateUrl: './full-view.component.html',
styleUrls: ['./full-view.component.css']
})
export class FullViewComponent implements OnInit {
public fulldata;
public antonyms = [];
public synonyms = [];
public resultObject;
public lexicalentries = [];
public varientforms = [];
public wordOrigin;
public currentWord;
public residueData = [];
public notes = [];
public show = false;
constructor(private router:Router,private route:ActivatedRoute,private http:WordService,private toastr:ToastrService) {}
ngOnInit() {
// Getting the parameter from URL
this.route.params.subscribe(routeParams => {
this.currentWord = routeParams.id;
this.http.getDefinition(routeParams.id).subscribe(
data => {
this.fulldata = data;
this.updateData(this.fulldata);
},
error => {
this.handleError(error);
}
);
});
}
public updateData(data) {
this.resultObject = data.results['0'];
this.lexicalentries = this.resultObject['lexicalEntries'];
// removing residue data from full data
this.residueData = this.lexicalentries.filter(
lexicalEntry => lexicalEntry.lexicalCategory !== 'Residual'
);
// making arrays empty for new data
this.antonyms = [];
this.synonyms = [];
this.wordOrigin = '';
this.notes = [];
this.extractData(this.residueData);
}
play(audio)
{
audio.play(); // play audio on clicking speak icon
}
public extractData(data) {
for(let singleData of data){
console.log(singleData); // printing the word
// extracting word origin data
if(singleData.entries['0'].etymologies){
this.wordOrigin = singleData.entries['0'].etymologies;
}
// extracting varient forms data
if(singleData.entries['0'].hasOwnProperty('varientforms')){
this.varientforms.push(singleData.entries['0'].varientforms['0'].text);
}
// extracting notes
if(singleData.entries['0'].hasOwnProperty('notes')){
const temp = [];
for(const note of singleData.entries['0'].notes){
temp.push(note);
}
const not = unionBy(temp, 'text');
this.notes = not;
}
}
this.getSyn();
this.toastr.success(`Definition of ${this.resultObject['word']} is Loaded`);
}
// function to get the synonyms
public getSyn() {
this.http.SynAnt(this.currentWord).subscribe(
data => {
let values = data;
this.separateData(values);
},
error => {
this.handleError(error);
}
);
}
// separate synonym and antonym into separate arrays
public separateData(values) {
const synonyms = [];
const antonyms = [];
for(const data of values.results['0'].lexicalentries){
for(const syn of data.entries['0'].senses){
if(syn.synonyms){
synonyms.push(syn.synonyms);
}
if(syn.antonyms){
antonyms.push(syn.antonyms);
}
}
}
this.separateSyn(synonyms);
this.separateAnt(antonyms);
}
// separating antonyms
public separateAnt(data) {
const temp = [];
data.map(i => {
i.map(j => {
temp.push(j.text);
});
});
this.antonyms = sortBy(uniq(temp));
}
// separating synonyms
public separateSyn(data) {
const temp = [];
data.map(i => {
i.map(j => {
temp.push(j.text);
});
});
this.synonyms = sortBy(uniq(temp));
}
// function to handle error responses
public handleError(error)
{
if(error.status === 404 || error.status === 414){
this.toastr.error('Try again with valid word');
}
else if(error.status === 403){
this.toastr.error(`Invalid credentials`,`Please enter correct details`);
}
else if(error.status === 414){
this.toastr.error(`Your word is too long`,`Please reduce the length of the word`);
}
else if(error.status === 500){
this.toastr.warning(`Something is broken`,`Please contact developer`);
}
else if(error.status === 502){
this.toastr.info(`Oxford Dictionaries API is down or being upgraded`,`Bad Gateway`);
}
else if(error.status === 503){
this.toastr.info(`Please try again later`, `Service Unavailable`);
}
else if(error.status === 504){
this.toastr.info(`Please try again later`, `Gateway timeout`);
}
}
}
full-view.component.html
<div class="mt-6 container-fluid">
<div class="mt-2 mb-3">
<app-search-box></app-search-box>
</div>
<div class="jumbotron z-depth-3" *ngIf="fullData">
<p> Definition of
<span class="text-secondary font-weight-bold">{{ resultObject.word }}</span> in English ({{ resultObject.language }}) </p>
<h1 class="h1 red-text text-capitalize"> {{ resultObject.word }} </h1>
<p *ngIf="wordOrigin" class="lead font-weight-normal">
<strong>Origin : </strong>
<span class="text-muted">{{wordOrigin}}</span>
</p>
<hr class="my-1">
<div *ngFor="let lexicalEntry of residueData">
<h4 class="blue-text h4-responsive">
<u>{{lexicalEntry.lexicalCategory}}</u> :
</h4>
<h6 class="font-weight-normal" *ngIf="lexicalEntry.pronunciations.length > 0">Pronunciations :
<span *ngFor="let pronunciations of lexicalEntry.pronunciations">
<span> {{ pronunciations.phoneticSpelling }}
<audio #audio [src]="pronunciations.audioFile"></audio>
<a (click)=play(audio)>
<i class="fa fa-volume-up" aria-hidden="true"></i>
</a>
</span>
</span>
</h6>
<p> Definitions :</p>
<span *ngFor="let sense of lexicalEntry.entries['0'].senses">
<p>
<i class="fa fa-arrow-right indigo-text" aria-hidden="true"></i> {{ sense.definitions }} </p>
</span>
<button class="btn btn-outline-secondary btn-rounded btn-sm waves-light" type="button" (click)="test.toggle()" (click)="show = !show"
mdbWavesEffect>Show More
<i class="fa ml-1" [ngClass]="show ? 'fa-minus' : 'fa-plus'" aria-hidden="true"></i>
</button>
<div class=" bg-vio p-2" [mdbCollapse]="isCollapsed" #test="bs-collapse">
<div *ngIf="lexicalEntry.entries['0'].senses">
<span>Examples :</span>
<ul *ngFor="let senses of lexicalEntry.entries['0'].senses">
<li #eg *ngFor="let example of senses.examples"> {{ example.text }} </li>
</ul>
</div>
</div>
<hr class="dropdown-divider m-2">
</div>
<div class="card pink darken-1 z-depth-2" *ngIf="varientforms.length > 0">
<div class="card-body">
<span class="white-text mb-0">
<span>Variant Forms : {{ varientforms }}</span>
</span>
</div>
</div>
<div class="card pink darken-1 z-depth-2 mt-2" *ngIf="notes.length > 0">
<div class="card-body">
<span class="white-text mb-0">
<span>Notes : </span>
<ul class="list-group">
<li class="list-group-item black-text" *ngFor="let note of notes">
<span class=" font-weight-bold blue-text">{{note.type | uppercase}} :</span>
<span> {{note.text}}</span>
</li>
</ul>
</span>
</div>
</div>
<hr class="dropdown-divider m-2" *ngIf="synonyms.length > 0">
<div class="row">
<div class="col-12" *ngIf="synonyms.length > 0">
<button class="btn btn-outline-primary btn-rounded btn-sm waves-light text-center" type="button" (click)="syn1.toggle()"
(click)="show = !show" mdbWavesEffect>
synonyms
<i class="fa ml-1" [ngClass]="show ? 'fa-minus' : 'fa-plus'" aria-hidden="true"></i>
</button>
<div class="card indigo z-depth-2" [mdbCollapse]="isCollapsed" #syn1="bs-collapse">
<div class="card-body">
<ul class="list-inline white-text mb-0">
<li class="list-inline-item" *ngFor="let syn of synonyms;let last=last"> {{syn}}{{last ? ' ' : ', '}} </li>
</ul>
</div>
</div>
</div>
<hr class="dropdown-divider m-2" *ngIf="antonyms.length > 0">
<div class="col-12" *ngIf="antonyms.length > 0">
<button class="btn btn-outline-primary btn-rounded btn-sm waves-light text-center" type="button" (click)="ant.toggle()" (click)="show = !show"
mdbWavesEffect>
antonyms
<i class="fa ml-1" [ngClass]="show ? 'fa-minus' : 'fa-plus'" aria-hidden="true"></i>
</button>
<div class="card indigo z-depth-2" [mdbCollapse]="isCollapsed" #ant="bs-collapse">
<div class="card-body">
<ul class="list-inline white-text mb-0">
<li class="list-inline-item" *ngFor="let syn of antonyms;let last=last"> {{syn}}{{last ? ' ' : ', '}} </li>
</ul>
</div>
</div>
</div>
</div>
</div>