Reputation: 743
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>
Upvotes: 60
Views: 35844
Reputation: 2932
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>
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.
Upvotes: 5
Reputation: 471
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$
.
Upvotes: 24
Reputation: 657318
The async
pipe does the subscription in view bindings
<h3>{{(game | async)?.name}}</h3>
The ?
is only necessary when null
values might be emitted.
Upvotes: 85