【问题标题】:Search bar Autocomplete from API来自 API 的搜索栏自动完成
【发布时间】:2019-12-13 19:47:31
【问题描述】:

我正在尝试创建一个带有自动完成功能的图书搜索栏,每次按键都会动态显示相关结果。一切正常,我正在获取数据,但结果未显示在下拉菜单中

使用 Angular 8 和 Material 8.2.3

我正在尝试创建一个带有自动完成功能的图书搜索栏,每次按键都会动态显示相关结果。一切正常,我正在获取数据,但结果未显示在下拉菜单中

    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>

【问题讨论】:

  • 你有一个stackblitz来重现这个问题吗?

标签: angular angular-material


【解决方案1】:

总工作示例,您可以在此StackBlitz Link

中找到

onChange() 方法 您必须首先通过管道 () 处理所有 rxjs 运算符,例如 filter、debounceTime、switchMap。在这里,当文本输入发生更改时,您可以先检查 valueChanges,然后在 switchMap() 中您可以触发服务 api 调用数据。

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<{}>; 
   })
}

这里,

  • 第一个 pipe() 运算符是 filter(),用于过滤用户输入的任何黑色空间。所以,没有什么需要 api 请求。
  • 第二个 pipe() 操作符是 debounceTime(500),用于等待停止用户输入。并且恰好在 5ms 之后通过 switchMap() 的 api 请求传递搜索字符串
  • 第三个 pipe() 操作符是 switchMap(),用于在每次 valueChanges 之后切换到一个新的 observable。

search.service.ts

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

【讨论】:

    【解决方案2】:

    您可以直接将创建的 observable 传递给自动完成控件:

    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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-01
      • 2012-11-12
      • 2018-10-26
      • 2018-06-30
      • 2011-09-19
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      相关资源
      最近更新 更多