设计牛津词典应用程序时出错

时间:2019-01-13 17:23:09

标签: javascript angular html5

我正在使用牛津字典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>

0 个答案:

没有答案