I have created this interface:
interface IGame {
name: string;
description: string;
}
I'm using it as an Observable and passing it as Input
to the Component
:
@Input() public game: Observable<IGame>;
I can see its value printed using the JSON pipe:
<h3>{{game | json}}</h3>
When binding to a specific property, nothing is displayed (just an empty string):
<h3>{{game.name}}</h3>
<h3>{{game.description}}</h3>
The async
pipe does the subscription in view bindings
<h3>{{(game | async)?.name}}</h3>
The ?
is only necessary when null
values might be emitted.
Using the *ngIf-As-Syntax factors out the async
pipe into a single call (and a single subscription).
<ng-container *ngIf="( game$ | async ) as game">
<h3>{{ game.name }}</h3>
<h3>{{ game.description }}</h3>
</ng-container>
This only creates one subscription to the observable, it removes the need for ?.
and makes working with the template much cleaner.
Note: I renamed the original example observable from game
to game$
.
NgRx 10 presented the @ngrx/component
package with the *ngrxLet directive - a convenient way to bind observables in templates.
Usage example:
<ng-container *ngrxLet="observableNumber$ as n">
<app-number [number]="n">
</app-number>
</ng-container>
You can even track all the observable notifications:
<ng-container *ngrxLet="observableNumber$; let n; let e = $error, let c = $complete">
....
</ng-container>
From the NgRx docs:
The current way of binding an observable to the view looks like that:
*ngIf="observableNumber$ | async as n"
. The problem is*ngIf
is also interfering with rendering and in case of a falsy value the component would be hidden. The*ngrxLet
directive takes over several things while making it more convenient and safe to work with streams in the template.
An explanatory tutorial about ngrxLet can be found here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With