Pipes keep formatting out of components and are reused across the whole app.
A pipe transforms a value for display: {{ value | pipeName:arg1:arg2 }}. Pipes can be chained, left to right.
Common built-in pipes from @angular/common (import them in the component's imports, or import CommonModule):
date:{{ createdAt | date:'mediumDate' }}or a format like'yyyy-MM-dd'.currency,number('1.0-2'= min 1 integer digit, 0 to 2 decimals),percent.uppercase,lowercase,titlecase,slice,keyvalue.jsonfor debugging objects.asyncsubscribes to an Observable or Promise and renders the latest value, unsubscribing automatically.
Formatting uses the app's locale (LOCALE_ID), so dates and currencies localise correctly.
A custom pipe is a class with @Pipe({ name }) implementing transform(value, ...args). Pipes are pure by default: Angular calls transform again only when the input value or arguments change by reference. That makes them cheap, but it also means mutating an array in place won't re-run a pure pipe. Impure pipes (pure: false) run on every change detection and should be avoided for anything expensive.
Pipes are better than calling a method in the template for formatting, since methods run on every change detection pass. For component-specific derived data, a computed signal is usually clearer.
Example
import { Component, Pipe, PipeTransform, signal } from '@angular/core';
import { CurrencyPipe, DatePipe, UpperCasePipe } from '@angular/common';
@Pipe({ name: 'initials' })
export class InitialsPipe implements PipeTransform {
transform(name: string, max = 2): string {
return name.split(' ').map((p) => p[0]).slice(0, max).join('');
}
}
@Component({
selector: 'app-invoice',
imports: [CurrencyPipe, DatePipe, UpperCasePipe, InitialsPipe],
template: `
<p>{{ customer() | initials }}</p> <!-- AL -->
<p>{{ customer() | uppercase }}</p> <!-- ADA LOVELACE -->
<p>{{ amount() | currency:'EUR' }}</p> <!-- €1,234.50 (en-US) -->
<p>{{ due() | date:'yyyy-MM-dd' }}</p> <!-- 2026-03-01 -->
`,
})
export class Invoice {
protected customer = signal('Ada Lovelace');
protected amount = signal(1234.5);
protected due = signal(new Date(2026, 2, 1));
}Remember
{{ value | pipe:arg }}formats values; chain pipes left to right- Import pipes like
DatePipeandCurrencyPipeinto the component - Custom pipes are pure by default and only re-run when inputs change by reference
Watch out for
- Mutating an array in place and expecting a pure pipe that filters it to update.