Search code examples
angularrxjsobservable

How to delete an element with async pipe once observable completed


lets say I have a div element with an observable that is emitting values:

<div *ngIf="(obseravle$ | async) as value"> {{ value }} </div>

I would like to remove the element from the DOM once i do this:

obseravle$.complete();

Is there an angular way to achieve that without subscribing to the component from the .ts file and using a flag?

Thanks a lot.


Solution

  • When the Observable completes you can emit one more value indicating that you want to hide the surrounding container. In this example I'm using endWith() that will emit after the source completes:

    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [AsyncPipe, NgIf, NgTemplateOutlet],
      template: `
        <ng-container
          [ngTemplateOutlet]="content"
          [ngTemplateOutletContext]="{$implicit: observable$ | async}"
        >
        </ng-container>
    
        <ng-template #content let-value>
          <ng-container *ngIf="value !== null">
            <h1>Value {{ value }}!</h1>
          </ng-container>
        </ng-template>
      `,
    })
    export class App {
      observable$ = range(1, 4).pipe(
        concatMap((val) => of(val).pipe(delay(1000))),
        endWith(null)
      );
    }
    

    I'm using [ngTemplateOutlet] only to store the value from the async pipe. I could use just *ngIf="a | async as value" but then it wouldn't show the container for values that equal to false such as "" or 0 which might be fine in your use-case so you can simplify the code a bit.

    Live demo: https://stackblitz.com/edit/stackblitz-starters-w2p2ly?file=src%2Fmain.ts