The Issue
Let’s imagine we’ve an observable which fetches a list of users:
All right. Suppose we got a mission to display each user field by a separated list. But there is a constraint, each list will be displayed differently. Thus, the appropriate template could be:
Let’s check how many subscriptions would be created in that way by adding a log when a subscription is created:
Here are the results of the Console:
Well, we notice that each usage of async pipe creates another subscription. Although these are three different *ngFor
, we’re talking about the same observable - so we’d expect that async pipe would use a single instance of a shared subscription.
In case there is an operator on the observable, for example, a map
operator which does a heavy business logic like calculating - that operator will be executed for each subscription individually.
Let’s see how to create a single subscription for users$
but still be able to use its result for each list.
The Solution
As part of Angular 4.0.0 - we introduced with the as
keyword. That keyword enables assigning a local variable in the component’s template. In other words, it means we’re able to use a variable (as much as we want) which points to the evaluated result of the async pipe.
Note: In general, assigning the result using the as
keyword isn’t necessarily for the async pipe but for all pipes.
To bind a local variable with the template, we need to wrap the template with the ng-container
directive.
In case that you’re not familiar with the ng-container
- it’s just a wrapper that enables to group multiple DOM elements (without adding an additional element to the DOM) and apply a structural directive on these elements (such as *ngFor
and *ngIf
).
It’s time to use the as
keyword:
Basically, what we do is to assign the result from the subscription as a local variable which is named users
. Notice we need a structural directive in order to interpret the as
keyword and for binding the users
variable with the result from the async pipe. That’s the reason we use *ngIf
.
If we’d like to use the users array for other purposes (for instance, printing its length) we could use the users
variable as well - as long as it’s evaluated inside that ng-container
scope.
Here’s attached the final result:
Indeed, we’re done.