Combine multiple *ngIf with an async pipe into one

Try to avoid using many async pipes in a single *ngIf directive. Move logic to use RxJs operators instead. See examples of how to do it correctly.

July 17, 2022 angularangular-15rxjs

Concat many observables object into one variable

Using many async pipes in single *ngIf means less readable code and it reduces performance because async is a pure pipe.

1
import { Component } from "@angular/core";
2
import { of } from "rxjs";
3
4
@Component({
5
template: ` <ng-container *ngIf="(pet$ | async) && !(cat$ | async)"> ... </ng-container> `,
6
})
7
export class ExampleComponent {
8
pet$ = of(true);
9
cat$ = of(false);
10
}

A better idea is to use RxJs operators to combine multiple conditions into a single observable object. For example, you can use combineLatest operator.

1
import { Component } from "@angular/core";
2
import { of, combineLatest, map } from "rxjs";
3
4
@Component({
5
template: ` <ng-container *ngIf="show$ | async"> ... </ng-container> `,
6
})
7
export class ExampleComponent {
8
private pet$ = of(true);
9
private cat$ = of(false);
10
11
show$ = combineLatest([this.pet$, this.cat$]).pipe(map(([pet, cat]) => pet && !cat));
12
}

Return null to hide section if conditions are not fulfilled

Using many *ngIf unnecessary increases a template’s size and complexity.

1
import { Component } from "@angular/core";
2
import { of } from "rxjs";
3
4
@Component({
5
template: `
6
<ng-container *ngIf="users$ | async as users">
7
<ng-container *ngIf="users.length > 1 && users.length < 5"> ... </ng-container>
8
</ng-container>
9
`,
10
})
11
export class ExampleComponent {
12
users$ = of(["Alice", "Bob", "Charlie", "Dave"]);
13
}

You can check conditions inside component logic, create an observable object and return null if conditions are not fulfilled.

1
import { Component } from "@angular/core";
2
import { map, of } from "rxjs";
3
4
@Component({
5
template: ` <ng-container *ngIf="show$ | async as users"> </ng-container> `,
6
})
7
export class ExampleComponent {
8
users$ = of(["Alice", "Bob", "Charlie", "Dave"]);
9
show$ = this.users$.pipe(map((users) => (this.showSection(users) ? users : null)));
10
11
private showSection(users: string[]): boolean {
12
return users.length > 1 && users.length < 5;
13
}
14
}

Section won’t be shown because *ngIf only render template when value is truthy. Than means when we return null section will be hidden.

Do you like the content?

Your support helps me continue my work. Please consider making a donation.

Donations are accepted through PayPal or Stripe. You do not need a account to donate. All major credit cards are accepted.

Leave a comment