【问题标题】:ngFor Observable with async pipe in ngIf displays no results在 ngIf 中使用异步管道的 ngFor Observable 不显示任何结果
【发布时间】:2019-08-27 08:23:11
【问题描述】:

我有一个不显示结果的下拉列表输入。它在带有异步的 ngIf 中。当我删除 ngIf 代码时会显示下拉列表,因此我认为它必须是 ngIf 检查或我设置测试可观察服务的方式。当我按下一个输入 1 个值的键时,没有显示任何内容,当我第二次输入一个键时,它会显示列表。

<div class="format-options" *ngIf="(definitions | async)?.length > 0">
  <div *ngFor="let definition of definitions | async" class="search-result">
    <div>{{definition.name}}</div>
    <div>{{definition.description}}</div>
  </div>
</div>

搜索服务:

searchTerm(term: string): Observable<Array<ObjectDefinition>>

    let observer = new Observable<Array<ObjectDefinition>>((subscription) => {

      const timer$ = interval(1000);

      timer$.subscribe(() => {
        console.log('timer 1 second');
        subscription.next(this.objectDefinitions);
        subscription.complete();
      });

    });

    return observer;
}

组件:

constructor(private definitionService: DefinitionService) {
    this.definitions = this.searchInput.valueChanges
                        .pipe(
                            tap(value => console.log('input')),
                            //startWith(''),
                            debounceTime(500),
                            //distinctUntilChanged(),
                            switchMap(value => this.definitionService.searchTerm(value))
                        );
  }

【问题讨论】:

  • 您是否介意详细说明您的代码。我真的不明白你想做什么?
  • 你不应该订阅服务,使用 rxjs 操作符。

标签: angular rxjs


【解决方案1】:

我猜第一个 *ngIf 通过 async 管道订阅。一旦返回结果,observable 就完成了,*ngFor 尝试订阅一个已经完成的 observable,它不会重播它的最后一次发射。您可以通过添加shareReplay(1) 管道来解决此问题:

this.definitions = this.searchInput.valueChanges.pipe(
  tap(value => console.log('input')),
  debounceTime(500),
  switchMap(value => this.definitionService.searchTerm(value)),
  shareReplay(1)
);

虽然整个searchTerm observable 看起来有点奇怪,你应该看看如何改进它,但很难看出你想在那里实现什么。您是否尝试将其消抖 1000 毫秒并且只发射一次?

为了防止在您的模板中使用双重订阅,您还可以稍微更改您的模板:

<ng-container *ngIf="definitions | async as defs">
  <div class="format-options" *ngIf="defs.length > 0">
    <div *ngFor="let definition of defs" class="search-result">
      <div>{{definition.name}}</div>
      <div>{{definition.description}}</div>
    </div>
  </div>
</ng-container>

【讨论】:

  • @MehdiBenmoha 我喜欢我们都使用as defs 的方式:D 我总是在末尾用$ 命名可观察对象的原因之一。
  • 是的,我也这样做,但我懒得更新他的ts代码xD
  • 像 debounce,一个定时响应,我想在项目中有一些可观察的示例代码,因为我是 rxjs 的新手
  • 替换一个http响应,也没有服务器设置
  • 您的服务代码可以简化为of(this.objectDefinitions).pipe(delay(1000))
【解决方案2】:

您可以像这样直接在 *ngIf 指令中设置异步操作的结果:

<div class="format-options" *ngIf="definitions | async as defs">
  <div *ngFor="let definition of defs" class="search-result">
    <div>{{definition.name}}</div>
    <div>{{definition.description}}</div>
  </div>
</div>

那么就不需要第二个异步管道了。

PS:永远不要订阅您的服务,最好使用 RxJs 运算符。

【讨论】:

  • 你的意思是第二个异步
  • 如果我不在服务中使用订阅,我将如何实现定时值?我正在尝试替换 http 响应,因为我没有服务器设置
  • 使用 rxJs 操作符,并且只订阅组件。你想延迟响应?所以使用延迟运算符
猜你喜欢
  • 1970-01-01
  • 2019-08-31
  • 2016-02-18
  • 1970-01-01
  • 2019-04-11
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多