Search code examples
angularobservableasync-pipe

How to update existing Observable in async pipe


I have an Observable that is subscribed to via the async-pipe.

<ng-container *ngIf="invitations$ | async as invitations">

This Observable is set in the ngOnInit:

this.invitations$ = this.getInvitations();

getInvitations is a private function that does the http-call and returns an Observable<Invitation[]>.

 private getInvitations(): Observable<Invitation[]> {
    return this.invitationService.getInvitations();
 }

Now, in a different function, I want to update this Observable, after a http-call has been completed. I want to send a reminder (triggered via a button in the template), and if it succeeds, I want to update the invitations.

sendReminder() {
    this.invitationService.postReminderEmail()
      .subscribe();
  }

So I have the line:

this.invitations$ = this.getInvitations();

But where do I put it? I know that the async-pipe will handle the unsubscription from the previous value and will resubscribe when I do this, so no memory leak.

Do I put it in the pipe?

   sendReminder() {
        this.invitationService.postReminderEmail().pipe(
         mergeMap(() => this.invitations$ = this.getInvitations())
          .subscribe();
      }

I think this line is a synchronous action, and I'm not really returning anything in the mergeMap (even though the compiler accepts this), so this does not seem to be right. I can change the mergeMap with tap, but I'm not sure about that either. Putting it in the subscribe feels like an indirect nested subscribe (because it will trigger a new subscribe via the async pipe), which I don't want. Do I make a Subject that the invitations$ can listen to, and I do a next() here, to trigger it? What I don't like about that, is that I have to put an empty array or something in the next to trigger it.

this.invitationsSubject.pipe(
      mergeMap(() => this.getInvitations()),
      takeUntil(this.destroyed)
    ).subscribe();

    this.invitations$ = this.invitationsSubject.asObservable();

Trigger:

this.invitationsSubject.next([])

This also does not seem to be a good solution (and it is more verbose).

What is the right approach?


Solution

  • If I understand you correctly, you simply want to update the invitations$ when you send a reminder?

    You could just update the invitations$ instead of creating a new observable, angular will unsubscribe from the previous observable.

    sendReminder(){
    this.invitations$ = this.invitationService.postReminderEmail().pipe(switchMap(() => this.getInvitations()));
    
    }