#What pipes are
A pipe is a small function you call from a template to turn a value into the thing you want to display: a Date into Mar 5, 2026, 1234.5 into $1,234.50, an observable into its latest value. You write the value, a |, then the pipe's name: {{ placed | date }}. The component keeps the raw data; the pipe only decides how it looks.
The mental model is a Unix pipe at display time. Data flows left to right through one or more transforms, and whatever comes out the right-hand end is what Angular writes into the DOM. Nothing flows back: the pipe never changes placed on the component, it just returns a new value for this binding.
Under the hood a pipe is a class with a transform() method and a @Pipe({ name }) decorator. When the template compiler sees placed | date, it creates one instance of DatePipe for that spot in the view and, during change detection, calls transform(placed) on it. Two things make pipes more than "a function call with funny syntax", and both come up in interviews:
- Purity — by default Angular remembers the last input and skips
transform()when the input hasn't changed (see Pure and impure pipes). That's what makes a pipe cheaper than calling a method from the template (Pipes vs method calls). - State — because each usage gets its own instance, a pipe can hold state between checks. The
asyncpipe uses that to keep a subscription open (The async pipe).
import { Component } from '@angular/core';
import { CurrencyPipe, DatePipe } from '@angular/common';
@Component({
selector: 'app-order-summary',
imports: [DatePipe, CurrencyPipe],
template: `<p>Placed {{ placed | date }} for {{ price | currency }}</p>`,
})
export class OrderSummary {
placed = new Date(2026, 2, 5, 14, 7);
price = 1234.5;
}imports: [DatePipe, CurrencyPipe]makes the two pipes available to this template. Built-in pipes live in@angular/commonand are standalone, so you import exactly the ones you use (the old NgModule world got them all at once fromCommonModule).- The template compiler sees
placed | dateandprice | currencyand creates oneDatePipeinstance and oneCurrencyPipeinstance for this view. - On the first change detection Angular calls
datePipe.transform(placed)andcurrencyPipe.transform(price). The component'splacedis still aDateandpriceis still the number1234.5— only the text written into the<p>is formatted. - The rendered text is
Placed Mar 5, 2026 for $1,234.50in the defaulten-USlocale (verified in a TestBed test).datewith no argument uses themediumDateformat;currencywith no argument usesUSD. - If you forget the import, the build fails with
NG8004: No pipe found with name 'date'.— the compiler checks pipe names just like component selectors.
Use a pipe for display formatting and light, reusable transforms of a value. Business logic, filtering a big list or anything that decides what data exists belongs in the component (ideally in a computed()) or a service; a pipe decides only how a value looks.