Search bar Autocomplete from API

╄→尐↘猪︶ㄣ 提交于 2020-01-22 02:47:06

问题


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 results are not showing on the dropdown menu

Using angular 8 and Material 8.2.3

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 results are not showing on the dropdown menu

    import { Component, OnInit } from '@angular/core';
    import { Store } from '@ngrx/store';
    import { AppState } from '../app.state/app.state';
    import { Observable } from 'rxjs/Observable';
    import { UserName } from '../../model/name.model';
    import { FormControl, FormGroup, FormBuilder } from '@angular/forms';
    import { MainService } from '../main.service';
    
    @Component({
      selector: 'app-search',
      templateUrl: './search.component.html',
      styleUrls: ['./search.component.css']
    })
    export class SearchComponent implements OnInit {
      searchForm: FormGroup;
    
      username: Observable<UserName[]>;
      searchTerm: string;
      searchResult: [];
      isLoading = false;
      errorMsg: string;
    
      constructor(private store: Store<AppState>, private searchService: MainService, private formBuilder: FormBuilder) {
        this.username = store.select('username');
       }
    
      ngOnInit() {
        this.searchForm = this.formBuilder.group({
          searchBar: ''
        });
        this.onChanges();
      }
    
      onChanges(): void {
        this.searchForm.get('searchBar').valueChanges.subscribe(val => {
          this.searchService.searchingValue(val).subscribe(function(data){
            this.searchResult = data.items;
          } );
    
        });
    
      }
     
      }

    <!-- <p>{{ username.username }}</p> -->
    <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" [value]="option">
                          <span>{{ option.volumeInfo.title }}</span>
    
                        </mat-option>
                      </ng-container>
                    </mat-autocomplete>
                  </mat-form-field>
              
            
    </form>

回答1:


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,

  • first pipe() operator is filter(), used for filter any black spaces entering by user. so, that nothing calls for api requesting.
  • second pipe() operator is debounceTime(500), used for waiting to stop user typing. and exactly after 5ms search string is passed on api request of switchMap()
  • Third pipe() operator is switchMap(), used to switch to a new observable, after every valueChanges.

search.service.ts

searchingValue(value){
    return of(this.bookDetails.filter( booksName => booksName.name.replace(/[\s]/g,'').toLowerCase().indexOf(value.toLowerCase()) === 0 ));
}



回答2:


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>


来源:https://stackoverflow.com/questions/59317455/search-bar-autocomplete-from-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!