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 👏