1

Could anyone help me with the issue. In a <div> element, I want to display the element when an Observable is evaluated available, and also display the content of the Observable value.

Please see the code below:

html

<div *ngIf="message$ | async">{{message$ | async}}</div>
<button (click)="onclick()">button</button>

ts

message$ = new Subject<string>();
ngOnInit() { this.message$.next(null);}
onclick() { this.message$.next("test");}

stackblitz example

When I click on the button, the <div> element is displayed because the *ngIf="message$ | async" is evaluated true, while the template interpolation value {{message$ | async}} has no value.

This is where I don't understand. Anyone know about it please help to explain, thanks. {{message$ | async}} dosen't work

P.S. I tried two other method to make it work (but still don't understand above mentioned problem):

1: use the as syntax: {{msg}};

2: use BehaviorSubject: message$ = new BehaviorSubject(null); it works

Johan Rin
  • 1,900
  • 2
  • 20
  • 42

2 Answers2

4

You have to define your message after the async pipe to make it available :

<div *ngIf="(message$ | async) as message">{{ message }}</div>
Johan Rin
  • 1,900
  • 2
  • 20
  • 42
0

The reason why this doesn’t work with a Subject is that it’s a race condition. The ngIf is not adding the second async pipe to the DOM and does not subscribe until after the subject has emitted Its value. So there is nothing to render at that time.

The biggest problem with this approach is your Observable is subscribed to twice. For example, if message$ was an HTTP request then two HTTP requests would be fired off, one for each async pipe.

Subjects are hot Observables, so they do not retain their value for the subscriber that subscribe after a value has been emitted.

The Behavior Subject works because it will retain its value for new subscribers.

Storing the value as a template variable ( as syntax) only has one subscription so this is why it works and is a better way of handling these.

JoshSommer
  • 2,550
  • 18
  • 23