One way to subscribe to observable in Angular is async pipe into the HTML template. It is easy but when you have several subscription use ng-container with *ngIf is a common solution, like :
<ng-container *ngIf="userAuth$ | async as user">
<span column-1 class="licence-name">
{{user.role}}
</span>
<ng-container *ngIf="domains$ | async as domains">
<ul *ngFor="let domain in domains">
<li>{{domain}}</li>
</ng-container>
<ng-container *ngIf="ads$ | async as ads">
<div *ngFor="let ad in ads">
{{ad.name}}
<div>
</ng-container>
<ng-container
</ng-container>
use Object :)
The ng-contanier generate too noise into the DOM, but we can simplify using object into a single *ngIf and grouping each subscription into it object like:
<ng-container *ngIf="{
user: userAuth$ | async,
domains: domains$ | async
} as state ">
<span column-1 class="licence-name">
{{state.user.role}}
</span>
<ul *ngFor="let domain in state.domains">
<li>{{domain}}</li>
</ul>
</ng-container>
Hopefully, that will give you a bit to help you avoid nested *ngIf for observable subscription.
If you enjoyed this post, share it.
Photo by John Barkiple on Unsplash
Top comments (3)
I strongly advise against using this kind of pattern.
First, you are breaking your
ngIf
clause, as*ngIf="userAuth$ | async as user"
will be false if user is undefined, whereas*ngIf="{ ... }"
will always be true.Thus your refactoring actually changes the behavior.
Secondly, in my opinion, this is just a hacky way to avoid an angular bug with nested
async
pipes.Those observables should be combined in the component using rxjs operators like
switchMap
orcombineLatest
. This way the logic of updating the component will be perfectly clear.Hi @mandel !
You're absolutely right,
combineLatest
is a great alternative! In fact, I talk about it in other article and how it can save you from the hassle of using multiple async pipes. 🎉Congrats 👏