To achieve peak performance, it is recommended to utilize rxjs in conjunction with the | async
pipe.
For instance, consider the sample application below:
@Component({
...,
template: `
<h1 *ngIf="isOk()">Hello world!</h1>
<input type="number" [(ngModel)]="a">
<input type="text" [(ngModel)]="b">`,
})
export class App implements DoCheck {
a = 0;
b = '';
isOk() {
console.log('ran function');
return (this.a === 3) && (this.b === 'foo');
}
ngDoCheck() {
console.log('DoCheck');
}
}
This leads to the following outcome:
https://i.sstatic.net/RlEkh.png
It's important to note that the function is executed multiple times upon each change, including when simply interacting with one of the textboxes.
If Observables are utilized instead, results will be as shown in this example:
@Component({
...,
template: `
<h1 *ngIf="isOk$ | async">Hello world!</h1>
<input type="number" [ngModel]="a$ | async" (ngModelChange)="a$.next($event)">
<input type="text" [ngModel]="b$ | async" (ngModelChange)="b$.next($event)">
`,
})
export class App implements DoCheck {
a$ = new BehaviorSubject<number>(0);
b$ = new BehaviorSubject<string>('');
isOk$: Observable<boolean>;
constructor() {
this.isOk$ = combineLatest([this.a$, this.b$])
.pipe(map(([a, b]) => {
console.log('ran function');
return (a === 3) && (b === 'foo');
}));
}
ngDoCheck() {
console.log('DoCheck');
}
}
The outcome of this approach can be viewed here:
https://i.sstatic.net/UUL6x.png
It should be observed that the rxjs map
function is only triggered upon changes in inputs, minimizing unnecessary executions.
Moreover, the ChangeDetection strategy can now be adjusted to OnPush
: