嵌套在 ngIf 中时,异步管道订阅无法正常工作

wct*_*ger 6 javascript rxjs typescript angular angular6

我有一个快速搜索框,我想要一个加载动画。我用ng-templatewithngIf来显示/隐藏这个动画。我有一些 li 嵌套在同一个 div 中,它使用异步管道订阅搜索结果 Observable 以显示结果。当*ngIf父 div上没有时,这个异步管道工作得很好,但是当我申请时它似乎不再订阅了ngIf。这是预期的行为吗?还是我做错了什么?

我的标记看起来像这样。

<input #searchBox type="text" (keyup)="itemLoading=true;searchTerm$.next(searchBox.value)"/>
<div *ngIf="!itemLoading else loading">
<!--Remove ngIf then items will display correctly when search-->
<!-- <div> -->
  <ul>
    <li *ngFor="let item of result$ | async ">{{item}}</li>
  </ul>
</div>
<ng-template #loading>
  <p>LOADING...</p>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

我正在使用 switchMap 来运行搜索:

private source = of(['apple', 'pear', 'banana']).pipe(delay(500));

  searchTerm$ = new Subject<string>();
  result$: Observable<string[]>;
  itemLoading = false;  

  constructor() {
    this.result$ = this.searchTerm$.pipe(
      tap(term => console.log('search term captured: ' + term)),
      debounceTime(300),
      distinctUntilChanged(),
      switchMap(() => this.source.pipe(
        tap(_ => {
            console.log('source reached');
            this.itemLoading = false;
          })
      ))
    );
  }
Run Code Online (Sandbox Code Playgroud)

ngIf出现在父 div 中时,“已到达源”消息永远不会记录在控制台中,并且加载模板会一直挂在那里。

这是我正在谈论的完整工作示例:https : //stackblitz.com/edit/angular-2ukcqu

Dan*_*nez 7

重写*ngIfas hidden 应该可以解决问题。result$ 不起作用的原因是因为在*ngIfitemLoading 为 false 之前不会将里面的那些元素添加到 dom 中。那时他们将订阅 result$,但该事件已经发生。

或者shareReplay(1)也可以在不需要重写任何其他内容的情况下实现这一点,因为当 Observable 也被订阅时,回复也会运行。

方案一

<div [hidden]="itemLoading">
<!-- ... -->
</div>
<div [hidden]="!itemLoading">
  <p>LOADING...</p>
</div>
Run Code Online (Sandbox Code Playgroud)

方案B

this.result$ = this.searchTerm$.pipe(
  //...
  shareReplay(1)
);
Run Code Online (Sandbox Code Playgroud)