Ошибка автозаполнения материала Angular 6 при выборе - PullRequest
0 голосов
/ 08 марта 2019

Я новичок в развитии веб-интерфейса. Я использую Angular 6 в своем проекте, и я хотел реализовать typeahead / auto-complete, который бы извлекал результаты из бэкэнда, используя сервис. Я могу получить результаты из короткого списка (на основе текста, предоставленного пользователем в поле ввода), однако, как только выбор сделан, снова вызывается this.docControl.valueChanges, что приводит к ошибке. Мой компонент называется DocumentSearch и выглядит следующим образом:

export class DocumentSearchComponent implements OnInit {
  docControl = new FormControl('');
  searchText: string;
  filteredOptions$: Observable<Document[]>;
  isLoading: boolean;

  @Output() documentSelected = new EventEmitter<Document>();

  constructor(private _documentService: DocumentService) { }

  ngOnInit() {
    this.filteredOptions$ = this.docControl.valueChanges
      .pipe(
        startWith(''),
        debounceTime(400),
        tap((text: string) => { this.isLoading = true; this.searchText = text; }),
        switchMap((text: string) => this.searchText ? this._documentService
          .getAllMatchingDocument(this.searchText.toLowerCase())
          .pipe(
            finalize(() => this.isLoading = false),
          ) : of([])
        )
      )
    ;
  } 

  public myChangeFunc(event, doc: Document) {
    if (event.source.selected) {
      this.documentSelected.emit(doc);
      this.searchText = doc.documentTitle;
    }
  }

  displayFn(doc?: Document): string | undefined {
     return doc ? doc.documentTitle : undefined;
  }

}

HTML-шаблон прост:

<form class="example-form">
  <mat-form-field class="example-full-width">
    <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="docControl"
           [matAutocomplete]="auto" >
    <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
      <mat-option *ngFor="let doc of filteredOptions$ | async" (onSelectionChange)="myChangeFunc($event, doc)"
              [value]="doc">
        <span>{{doc.documentTitle}}}</span>
        <small> | ID: {{doc.documentID}}</small>
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>

Когда из предложенных вариантов выбран один из вариантов, на консоль выдается следующая ошибка. ERROR TypeError: _this.searchText.toLowerCase is not a function. Кроме того, myChangeFunc вызывается с нулевым значением в doc.

Любая помощь приветствуется. По-видимому, при выделении запускается this.docControl.valueChanges, что тоже с объектом Document вместо текста в поле ввода. Я явно объявил text как строку, надеясь на исключение, приведенное к классу, но безрезультатно.

1 Ответ

0 голосов
/ 08 марта 2019

Похоже, что вы используете фильтрацию на стороне сервера с помощью метода getAllMatchingDocument.

Вы можете получить список соответствующих документов из API, если введено правильное значение, с помощью следующего:

// component variable to keep documents
docs: Observable<Document[]>;

// When the value changes, retrieve filtered list from back-end
this.docControl.valueChanges
  .pipe(startWith(null), debounceTime(400))
  .subscribe(val => {
    // only if the value is a valid string and not a selected doc object
    if (typeof val === 'string') {
      this.isLoading = true;
      // Update docs
      this._documentService
        .getAllMatchingDocument(val === null ? '' : val.toLowerCase())
        .subscribe(
          results => {
            this.docs = results;
            this.isLoading = false;
          },
          error => {
            console.log('Error');
          }
        )
    }
  });

Изменить ngFor:

<form class="example-form">
  <mat-form-field class="example-full-width">
    <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="docControl"
           [matAutocomplete]="auto" >
    <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
      <mat-option *ngFor="let doc of docs" [value]="doc">
        <span>{{doc.documentTitle}}}</span>
        <small> | ID: {{doc.documentID}}</small>
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>
...