Reputation: 486
I want to write a collapsible component which has an "Expand" button that opens a list of items. This list is created through a web request, and I'm wondering when this request happens - since to my understanding the async
pipe is like a subscription and the ngIf
would cause the component subscribing to be recreated, I would expect the value of the request to only be available once, however it is created each time I 'show' the expander.
Inside my AppComponent
I have this logic:
data$ = of('expensive data from server').pipe(
take(1),
tap(() => console.log('data from server emit!')),
// shareReplay(1),
finalize(() => console.log('complete!'))
);
showSon = true;
The template is like this:
<button (click)="showSon=!showSon">Click me!</button>
<p *ngIf="showSon">
<ng-container *ngIf="data$ | async as data">
<div>{{data}}</div>
</ng-container>
</p>
My understanding is that since the observable is created via of
, that it should fire its value once and then complete, confirmed by the console logs. However I'm surprised that every time I show the element inside the ngIf
, I still get a value even though async
is now subscribing to a completed observable that is not a ReplaySubject
.
I think using shareReplay(1)
would solve the issue of making multiple web requests, but I still don't understand how the single-use observable is repeatedly available whenever the template inside the ngIf
is recreated.
Upvotes: 0
Views: 599
Reputation: 458
MikeOne's comment is correct. Everytime the If is true, the element gets recreated.. so the async pipe re-subscribes to the data$ observable causing it to emit again..
Your solution is also correct, to use shareReplay(1)
as you've mentioned.
Upvotes: 2