Auto-Subscribe in the Template
The Async Pipe
The async pipe subscribes to an Observable or Promise in the template and unsubscribes automatically when the component is destroyed.
What you'll learn
- Render Observable values with the async pipe
- Combine it with @if and @for control flow
- Bind the unwrapped value to a local name
async is the simplest way to display an Observable in a template. It subscribes when the view renders, pushes new values into the binding, and unsubscribes automatically — no manual cleanup.
Basic usage
import { Component, inject } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { UsersService } from './users.service';
@Component({
selector: 'app-users',
standalone: true,
imports: [AsyncPipe],
template: `<p>{{ count$ | async }} users</p>`,
})
export class UsersComponent {
count$ = inject(UsersService).count();
} With control flow
The bind-to-variable form (as user) lets you reference the unwrapped value multiple times.
@if (user$ | async; as user) {
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
} @else {
<p>Loading...</p>
}
@for (item of items$ | async; track item.id) {
<li>{{ item.label }}</li>
} Why it matters
Every async is one less manual subscription you can forget to clean up. It also plays nicely with OnPush change detection — the pipe marks the view dirty only when a new value arrives.
Or use a signal
In modern Angular, toSignal is often nicer because the result is just a value you can use in expressions without piping:
import { toSignal } from '@angular/core/rxjs-interop';
user = toSignal(this.users.getCurrent()); <h1>{{ user()?.name }}</h1> Both styles work — pick whichever feels clearer for the component at hand.
computed() & effect() →