2

I have a service that has some asynchronous stuff to do, how can I postpone a data binding render until the service has done its asynchronous work?

this.sessionService.onSessionChange().subscribe(function(session) {
    console.log(session);
    self.user = session.user;
});

Service:

onSessionChange(): Observable<Session> {
    return this.sessionObservable.asObservable();
}

The user is undefined because the session isn't ready yet:

<h4>Hi {{user.name}}.</h4>

How can I use a pipe with my onSessionChange observable?

4 Answers 4

3

In Angular4, a common idiom is to use the new as keyword as follows:

<ng-container *ngIf="session$ | async as session">
                                 <!-- ^^^^^^^^^^  "as" keyword -->
  <h4>Hi {{session.user.name}}</h4>
</ng-container>

This is even more useful if you are going to use session in more than one place in your template.

<ng-container> is a place to hang *ngIf or *ngFor without adding more nodes to the DOM.

Sign up to request clarification or add additional context in comments.

3 Comments

This isn't working, it is not displaying. Do I have to modify anything else?
I did get it working with a Promise but I want to use an observable
A possible downside to this approach is that anything in ng-container wont appear until session$ is returned.
1

As @Sajeetharan answered, you can use safe navigation operator to avoid undefined error thrown from template.

Just as you stated at your question's header, you can use Async Pipe to subscribe/unsubscribe to Observable automatically.

Step1: expose the Observable at your component:

// expose Observable in order to access at template
user$: any;
constructor(private sessionService: SessionService) {
  this.user$ = this.sessionService.onSessionChange();
}

Step2: use Async Pipe at your template to subscribe to the created Observable

<h4>Hi {{(user$ | async)?.user.name}}.</h4>

Working DEMO

8 Comments

is there any reason I should use an async pipe rather than the safe navigation operator?
@el_pup_le they don't have any conflicts. But by using async pipe, you don't need to unsubscribe from the observable at ngOnDestroy to prevent from memory leak. This is because async pipe will do it automatically for you.
The ? following (user$ | async) is unnecessary.
@torazaburo can you explain why? I was thinking user is not belong to (user$ | async) until response is back.
@k11k2 you can just confirm by removing ?. here is what happened. plnkr.co/edit/auVjlFt1fkJSWw9k3bmz?p=preview
|
0

You can handle this way too using safe navigation operator,

<h4>Hi {{user?.name}}.</h4>

Comments

0

Use the pluck operator to have an async property:

At the component:

this.userName$ = this.sessionService.onSessionChange().pluck('user', 'name')

At the template:

<h4>{{ userName$ | async }}</h4>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.