I need to render data from different ngrx stores based on some flag. Both stores gives same type of data.
Approach 1
<ng-contaier *ngIf="flag$ | async; else anotherStoreData">
<ng-container *ngIf="store1$ | async as store1">
<div>{{ store1?.prop1 }}</div>
<div>{{ store1?.prop2 }}</div>
</ng-container>
</ng-contaier>
<ng-template #anotherStoreData>
<ng-container *ngIf="store2$ | async as store2">
<div>{{ store2?.prop1 }}</div>
<div>{{ store2?.prop2 }}</div>
</ng-container>
</ng-template>
flag$: Observable<boolean>
store1$: Observable<Store>
store2$: Observable<Store>
ngInit() {
flag$ = streamService.userNewStore();
store1$ = this.store.select(<someselector1>);
store2$ = this.store.select(<someselector2>);
}
Approach 2
<ng-container *ngIf="store$ | async as store">
<div>{{ store?.prop1 }}</div>
<div>{{ store?.prop2 }}</div>
</ng-container>
store$: Observable<Store>
ngInit() {
streamService.userNewStore()
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((flag) => {
store$ = flag ? this.store.select(<someselector1>) : this.store.select(<someselector2>);
});
}
In Approach1 I am duplicating template, which is fine for small template - but if it is big then i am thinking about Approach 2.
In Approach2 streamService can change the flag at any time, in that case what will happen to the previous subscription in the template with async pipe. Will it lead any memory leak?
Is there any other alternatives that I can use, please suggest.
Having just checked the source code for the Async pipe, it appears that it will unsubscribe if the Observable changes.
You can see this in line 100 of the file:
if (obj !== this._obj) {
this._dispose();
return this.transform(obj as any);
}
If the value being passed in is not the one currently held in memory, it calls this.dispose
, which in turn unsubscribes.
With that in mind, I would definitely prefer the 2nd approach