首页 > 解决方案 > ngbTypeahead 搜索结果丢失

问题描述

我目前正在编写一个ngbTypeahead搜索,但我被困住了,因为我从未真正使用过 Observables,这是ngbTypeahead 搜索的预期返回类型。

我的组件中的搜索功能如下所示:

  search: OperatorFunction<string,  readonly LoqateResponseModel[]> = (text$: Observable<string>) => {
return text$.pipe(
  switchMap(term => this.addressService.searchAddress(term, this.countryCode)),
  map(results => {
    const searchResults = results[LoqateKeyEnum.ITEMS] as [];
    const searchResultLoqateModels: LoqateResponseModel[] = [];
    searchResults.forEach(result => {
      searchResultLoqateModels.push(new LoqateResponseModel(
        result[LoqateKeyEnum.ID],
        result[LoqateKeyEnum.TYPE],
        result[LoqateKeyEnum.TEXT],
        result[LoqateKeyEnum.HIGHLIGHT],
        result[LoqateKeyEnum.DESCRIPTION]));
    });
    return searchResultLoqateModels;
  })
);

}

resultFormatter = (loqateResponse: LoqateResponseModel): string => loqateResponse.display();

我正在进行 loqate 搜索,并将结果作为模型对象存储在列表中并返回它们。

public searchAddress(searchValue, countryCode): Observable<object> 
  {
    const httpParams = new HttpParams();
    return this.httpClient.post(this.addressSearchUrl, {}, {
      headers: this.headers,
      params: new HttpParams()
        .set('Key', loqateKey)
        .set('Text', searchValue)
        .set('Origin', countryCode)
    });
  }

模型如下所示:

export class LoqateResponseModel {
  constructor(
    public id: string,
    public type: LoqateTypeEnum,
    public text: string,
    public highlight: string,
    public description: string) {
  }

  public isAddress(): boolean { return this.type === LoqateTypeEnum.ADDRESS; }
  public display(): string { return this.text + ', ' + this.description; }
}

现在我想,一个列表LoqateResponseModels作为结果存储search,然后这些列表项中的每一个都被正确格式化,以通过resultFormatter.

tldr:我想使用 ngbTypeahead 搜索某些内容并从 API 端点查询搜索词,并在 typeahead 弹出窗口中显示搜索结果。

编辑:我已经编辑了答案,这段代码正在运行。

标签: angularjstypescriptrxjsrxjs-observables

解决方案


我想你正在寻找switchMap. 该运算符将为您订阅一个可观察的源并发出其结果:

您不想这样做return null,您只需通过管道修改返回可观察对象。

您的操作员函数应该接受一个可观察对象并返回一个可观察对象。您的 observable 可以简单地用于switchMap将传入映射text到 api 调用。

search: OperatorFunction<string, readonly LoqateResponseModel[]> = text$ => 
    text$.pipe(
        switchMap(text => this.searchAddress(text))
    );

每次switchMap收到一些text,它都会为你做一些事情:

  1. 订阅searchAddress(text)
  2. 从此订阅发出结果
  3. 停止发出以前订阅的结果

推荐阅读