3

I have an observable (or subject) in an angular 4 component, and I'm using that in the template with an async pipe, something like this:

<div *ngIf="(orderObservable | async) as order; else noOrder ">
    The active order was created at {{ order.created_at }}
</div>
<ng-template #noOrder>
    There is no active order at the moment. Sorry. 
</ng-template>

This works like a charm as long as the order does not exist, or is retrieved via HTTP call. In the code this looks something like this:

this.orderObservable = OrderService.getActive();

If this call returns an observable with an order, it gets displayed in the template. If it doesn't, the #noOrder template is displayed.

Now my question is: If I change the observable to a subject, and the currently active order does not exist anymore (i.e. because it was submitted or closed), is there any way to delete the subject, or pass something into the subject, so the template displays the #noOrder template instead of the one that displays the observable content, after it displayed the latter already?

R. Wenger
  • 288
  • 3
  • 15

1 Answers1

3

Subject is an Observable so it works the same. You just have to call complete() to tell the template that no more data is coming and therefore trigger the else condition.

this.subject = new Subject();
if(data) {
     this.subject.next(data);
}
this.subject.complete();

In the above example the complete() is always called. Which is a good practice when you aren't trying to stream a sequence of items. The example only emits a value if the value exists.

Note: If there are no subscribers at the time next is called. No one will receive the data. If you know the template will render after you call next you might want to use ReplaySubject instead. Which emits the last n'th items.

Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • Thanks for your reply. But this doesn't work for me, even if the subject is complete, the template still displays whatever came through the subject last. – R. Wenger Jul 15 '17 at 08:47
  • @R.Wenger you can use the `exhaust`operator to emit a `false` value after the first observable has completed. `Observable.of(this.subject,false).exhaust()` – Reactgular Jul 15 '17 at 12:55