I am beginning to get some proficiency in RxJS operators but I still have difficulty with some of them. In implementing a search component I have the following code:
searchResult$: Observable<LunrDoc []>;
searchResultLength$: Observable<number>;
ngAfterViewInit(): void {
// observable to produce an array of search hits
this.searchResult$ = fromEvent<Event>(this.searchInput.nativeElement, 'keyup').pipe(
debounceTime(1000),
switchMap(e => this.ss.search((e.target as HTMLTextAreaElement).value)),
share()
);
// observable to return the length of the array
this.searchResultLength$ = this.searchResult$.pipe(
map(sr => sr ? sr.length : 0),
share()
);
}
And this is used in the template like this:
<p *ngIf="(searchResultLength$ | async) > 0">
Total Documents: {{ (searchResultLength$ | async) | number }}
</p>
<p *ngFor="let doc of (searchResult$ | async)">
<span *ngIf="doc.path" [routerLink]="doc.path" style="color: darkblue; font-weight: bold; text-underline: darkblue; cursor: pointer">
{{ doc.title }}
</span>
{{ doc.content.substring(0, 400) }}
</p>
What happens is when a non-null array is emitted by the searchResult$ observable the rendered result in the first paragraph element as "Total Documents:" without a number after it. The *ngFor decorated paragraph works exactly as expected.
The reason I believe is that the second async pipe gets activated and subscribes to the shared observable after the last value gets emitted. So it never gets a "next" call.
Is there an RxJS operator to use instead of share to fix this situation? Or did I miss something else?
shareReplay(1)instead. - Ingo Bürkshareat all, do you really need it? - MoxxiManagarm