Pipes

Angular · Essentials · 9 min

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.
  • json for debugging objects.
  • async subscribes 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 DatePipe and CurrencyPipe into 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.

Check yourself

  1. A pure custom pipe filters an array. You push a new item into the same array. Does the displayed result change?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: angular.dev/guide/templates/pipes

Builds on

Unlocks

Nothing builds on this yet.