I\'m trying to create a book search bar with autocomplete that will show relevant results dynamically with each keypress. Everything is working and I\'m getting the data, but re
You can directly pass the created observable to the autocomplete control :
ts
...
searchResult: Observable;
onChanges(): void {
this.searchResult = this.searchForm.get('searchBar').valueChanges.pipe(
switchMap(val => this.searchService.searchingValue(val))
);
}
...
html
<h1>Book Search</h1>
<form [formGroup]="searchForm">
<!-- <mat-form-field>
<input type="text" matInput formControlName="searchBar" [matAutocomplete]="auto">
</mat-form-field> -->
<mat-form-field>
<input matInput placeholder="Search" aria-label="State" [matAutocomplete]="auto" formControlName="searchBar">
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option *ngIf="isLoading" class="is-loading">Loading...</mat-option>
<ng-container *ngIf="!isLoading">
<mat-option *ngFor="let option of searchResult | async" [value]="option">
<span>{{ option.volumeInfo.title }}</span>
</mat-option>
</ng-container>
</mat-autocomplete>
</mat-form-field>
</form>
Total working, example you can find out here in this StackBlitz Link
onChange() method you have to pipe () first of all rxjs operators like filter, debounceTime, switchMap. here when text input is changed you can check valueChanges first and then in switchMap() you can fire services api calling of data.
onChanges(){
this.searchForm.get('searchBar').valueChanges.pipe(
filter( data => data.trim().length > 0 ),
debounceTime(500),
switchMap( (id: string) => {
return id ? this.serachService.searchingValue(id.replace(/[\s]/g,'')) : of([]);
})
).subscribe(data =>{
this.searchResult = data as Array<{}>;
})
}
here,
search.service.ts
searchingValue(value){
return of(this.bookDetails.filter( booksName => booksName.name.replace(/[\s]/g,'').toLowerCase().indexOf(value.toLowerCase()) === 0 ));
}