Объекты, передаваемые методом фильтра (для поля автозаполнения material.angular.io), становятся неопределенными - PullRequest
0 голосов
/ 06 мая 2019

Я попытался реализовать функцию автозаполнения angular.material.io . Однако, пытаясь закодировать его в своем коде, я сталкиваюсь с ошибкой, связанной с неопределенными параметрами Я не знаю, почему это именно так.

Это мой реализованный машинописный код.

export class BooksComponent implements OnInit {
  private books: Array<Book> = [];
  //Autofillers & form controllers
  private bookCtrl = new FormControl();
  private filteredBooks: Observable<Book[]>;

  constructor() { 
    //Replace this in the future with data passed from the API
    JSONBooks.forEach(book =>
        this.books.push(new Audiobook(book.title, book.description, book.ISBN, book.image, book.price, book.amazonLink,
          book.publisher, book.amountOfChapters, book.soldCopies, book.adaptedForScreens, book.dateAdded, book.rating, book.amountOfHours))
      );
    //Formcontrol and autofills
    if (this.books) {
      this.filteredBooks = this.bookCtrl.valueChanges
      .pipe(
        startWith(''),
        map(book => book ? this.filterBooks(book) : this.books.slice())
      );
    }
    }

    ngOnInit() {}

    private filterBooks(value: Book): Book[] {
      return this.books.filter(
        //Matches book title
        book => book.getTitle.toLowerCase().indexOf(value.getTitle.toLowerCase()) === 0
        );
    }
}

Это мой реализованный HTML-код.

Я бы хотел найти книгу с названием

    </p>
      <form>
        <mat-form-field>
          <input matInput placeholder="Title" aria-label="Title" [matAutocomplete]="auto" [formControl]="bookCtrl">
          <mat-autocomplete #auto="matAutocomplete">
            <mat-option *ngFor="let book of filteredBooks | async" [value]="book.getTitle">
              <span>{{book.getTitle}}</span>
            </mat-option>
          </mat-autocomplete>
        </mat-form-field>
      </form>
    <p>

Вывод на консоль, строка 118 ссылается на мой машинописный код, этот раздел: .indexOf(value.getTitle.toLowerCase())

core.js:15723 ERROR TypeError: Cannot read property 'toLowerCase' of undefined
    at books.component.ts:118
    at Array.filter (<anonymous>)
    at BooksComponent.push../src/app/books/books.component.ts.BooksComponent.filterBooks (books.component.ts:116)
    at MapSubscriber.project (books.component.ts:62)
    at MapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:35)
    at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber.notifyNext (mergeMap.js:84)
    at InnerSubscriber.push../node_modules/rxjs/_esm5/internal/InnerSubscriber.js.InnerSubscriber._next (InnerSubscriber.js:15)
    at InnerSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54)
    at SafeSubscriber.schedulerFn [as _next] (core.js:13514)

Я проверял несколько раз, но не могу найти проблему в моем коде.

ПРИМЕЧАНИЕ: this.books заполняется и свойства могут быть прочитаны. Такие методы, как book.getTitle и т. Д., Также работают. Каким-то образом объект не передается методу filterBooks.

Ответы [ 3 ]

0 голосов
/ 06 мая 2019

В вашем коде конструктора вы используете this.bookCtrl.valueChanges.pipe (). Функция pipe () возвращает Observable. поэтому вам нужно подписаться на эту наблюдаемую и назначить для нее переменную this.filteredBooks.

this.bookCtrl.valueChanges
      .pipe(
        startWith(''),
        map(book => book ? this.filterBooks(book) : this.books.slice())
      )
      .subscribe((books) => this.filteredBooks = books);

См. Документацию для наблюдаемых: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html

0 голосов
/ 07 мая 2019

this.bookCtrl - это элемент управления для текстового поля.Таким образом, this.bookCtrl.valueChanges испускает текст в текстовом поле.

Я полагаю, что следующий код решит проблему.

// Formcontrol and autofills
if (this.books) {
  this.filteredBooks = this.bookCtrl.valueChanges
    .pipe(
      startWith(''),
      map(bookName => bookName ? this.filterBooks(bookName) : this.books.slice())
    );
}

И функция filterBooks:

  private filterBooks(bookName: string): Test[] {
    return this.books.filter(
      // Matches book title
      book => book.getTitle.toLowerCase().indexOf(bookName.toLowerCase()) === 0);
  }

Кроме того, поскольку в шаблоне html используются bookCtrl и filteredBooks, рекомендуется изменить общедоступные модификаторы доступа.Для получения дополнительной информации об этом: "private" и "public" в угловом компоненте

0 голосов
/ 06 мая 2019

Добавьте простое условие if, чтобы проверить, что value не равно нулю

 this.books.filter(
        //Matches book title
        book => {
             if(!value.getTitle) return false
             return book.getTitle.toLowerCase().indexOf(value.getTitle.toLowerCase()) === 0
        } );
...