Chapter 13: Pipes and Defer in Angular
Pipes are one of Angular’s most powerful template features. They let you transform values for display without changing the underlying data. Meanwhile, Angular v17 introduced @defer blocks, which delay rendering until certain conditions are met. Together, these features improve readability, performance, and user experience.
13.1 What Are Pipes?
A pipe is a function that transforms data in templates.
Example:
<p>{{ today | date }}</p>
Here, the date pipe formats a Date object into a human-readable string.
13.2 Built-in Pipes
Angular ships with many useful pipes:
- DatePipe:
{{ today | date:'short' }} - CurrencyPipe:
{{ price | currency:'USD' }} - DecimalPipe:
{{ num | number:'1.2-2' }} - PercentPipe:
{{ ratio | percent }} - AsyncPipe:
{{ data$ | async }} - SlicePipe:
{{ items | slice:0:3 }}
✅ Pipes are pure by default — they only re-run when input values change.
13.3 Custom Pipes
You can create your own pipes for specific transformations.
Example: CapitalizePipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'capitalize',
standalone: true
})
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
Usage:
<p>{{ 'angular' | capitalize }}</p>
<!-- Output: Angular -->
13.4 Pure vs Impure Pipes
- Pure pipes (default): Only re-run when input changes (efficient).
- Impure pipes (
pure: false): Re-run on every change detection cycle.
Use impure pipes sparingly (e.g., for filtering arrays in real time).
13.5 The Async Pipe
The async pipe is special: it subscribes to Observables or Promises automatically and unsubscribes when the component is destroyed.
Example:
<p *ngIf="user$ | async as user">Hello {{ user.name }}</p>
✅ Avoids manual .subscribe() and memory leaks.
13.6 Pipes vs Signals
With Angular signals, some transformations can move into computed signals.
Example with signals:
name = signal('angular');
capitalized = computed(() => this.name().toUpperCase());
Template:
<p>{{ capitalized() }}</p>
✅ Use pipes for template-level formatting.
✅ Use signals for state transformations in TypeScript.
13.7 The New @defer Block
Angular v17 introduced @defer, a structural block directive that delays rendering of parts of the template until:
- The component is idle.
- A specific trigger happens.
- Or manually specified conditions are met.
This improves performance by not rendering heavy components immediately.
Example: Lazy Component Rendering
@defer {
<expensive-chart></expensive-chart>
} @placeholder {
<p>Loading chart...</p>
}
✅ The <expensive-chart> component is only rendered when the app is idle.
✅ @placeholder shows interim UI.
Example: Conditional Defer with Triggers
@defer (on viewport) {
<app-ads-banner></app-ads-banner>
}
Here, the banner loads only when it enters the viewport (like lazy-loading images).
Example: Defer with Timer
@defer (on timer(5s)) {
<app-hint-message></app-hint-message>
}
This shows a hint only after 5 seconds.
13.8 Pipes vs @defer
| Feature | Pipes | @defer |
|---|---|---|
| Purpose | Transform values for display | Control when to render content |
| Scope | Data formatting in templates | UI performance optimization |
| Example | `{{ price | currency }}` |
| Complement | Works with @defer to format values | Works with pipes for final output |
13.9 Summary
- Pipes transform data directly in templates.
- Angular ships with powerful built-in pipes (
date,async,currency, etc.). - You can create custom pipes for reusable formatting.
- Pipes are pure by default but can be impure.
- Signals can handle some transformations outside templates.
- The new
@deferblock delays rendering for better performance. - Together, pipes and
@deferimprove both data presentation and app responsiveness.