Pipes in Angular
Transforming data for display right in the template with built-in pipes and pipes you write yourself.
阅读需 2 分钟
A pipe takes a value and transforms it for display, without changing the underlying data. Instead of formatting a date or rounding a number in the component class and storing the formatted version, you format it inline in the template with the | syntax.
Built-in pipes
<p>{{ publishedAt | date:'longDate' }}</p>
<p>{{ price | currency:'USD' }}</p>
<p>{{ title | uppercase }}</p>
<p>{{ description | slice:0:100 }}...</p>export class ArticleComponent {
publishedAt = new Date('2026-03-14');
price = 49.99;
title = 'getting started with angular';
description = 'A long description that will be truncated for the preview card...';
}Each pipe takes the expression on its left as input, and anything after a colon as a parameter — date:'longDate' formats the date in a long, readable style, and slice:0:100 takes the first 100 characters. Pipes can be chained too: {{ title | uppercase | slice:0:20 }} runs left to right.
Why not just format it in the class?
You could write a formattedPrice getter on the component instead, and for a one-off case that's fine. Pipes earn their place when the same transformation is needed in several places, or when it should stay purely about display — the underlying price stays a plain number, usable in calculations, while the pipe only affects what's rendered. Angular also optimizes pure pipes (the default kind) to re-run only when their input actually changes, rather than on every change-detection cycle.
Writing a custom pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'timeAgo',
})
export class TimeAgoPipe implements PipeTransform {
transform(value: Date): string {
const seconds = Math.floor((Date.now() - value.getTime()) / 1000);
if (seconds < 60) return 'just now';
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return `${minutes}m ago`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h ago`;
return `${Math.floor(hours / 24)}d ago`;
}
}<p>{{ comment.postedAt | timeAgo }}</p>The name in @Pipe is the string used in the template (timeAgo), and transform is the method Angular calls with the piped value as its first argument, plus any parameters after the colon as additional arguments. Once declared, a custom pipe needs to be added to a component's imports array (standalone pipes work the same way as standalone components) before templates using it will compile.
A word of caution
Keep pipe logic fast and free of side effects — a transform method runs during change detection, potentially many times per second, so anything slow (a network call, heavy computation without caching) inside a pipe will visibly slow down the whole app. If a transformation is expensive, compute it once in the component and store the result, rather than pushing that cost into a pipe that re-runs constantly.