Skip to content
Angular ng pipes 4 min read

Pipes Overview

Pipes are Angular’s declarative way to transform a value for display without changing the data behind it. You apply one in a template with the pipe operator |, reading like a sentence: take this value, send it through that transformer, render the result. They keep components lean — formatting logic stays in the template where the formatting happens — and the framework caches their output efficiently. Almost every template you write will lean on a pipe for dates, currency, casing, or async values.

The pipe operator

A pipe takes the expression on its left, passes it to the pipe named on the right, and the pipe returns a transformed value. The original data is untouched; only what the user sees changes.

import { Component } from '@angular/core';
import { UpperCasePipe, DatePipe, CurrencyPipe } from '@angular/common';

@Component({
  selector: 'app-receipt',
  standalone: true,
  imports: [UpperCasePipe, DatePipe, CurrencyPipe],
  template: `
    <p>{{ name | uppercase }}</p>
    <p>{{ issued | date:'mediumDate' }}</p>
    <p>{{ total | currency:'USD' }}</p>
  `,
})
export class ReceiptComponent {
  name = 'invoice #2048';
  issued = new Date('2026-06-14');
  total = 42.5;
}

Output:

INVOICE #2048
Jun 14, 2026
$42.50

In standalone components, each built-in pipe is a self-contained class you import into the component’s imports array. The name, issued, and total properties stay in their natural form on the class — strings and a Date — and only the rendered text is transformed.

Passing parameters

Many pipes accept arguments. You supply them after the pipe name with a colon, and you can pass several by chaining more colons. Arguments are ordinary template expressions, so they can be literals or component properties.

<!-- format string -->
<p>{{ issued | date:'fullDate' }}</p>

<!-- currency code, display style, and digit format -->
<p>{{ total | currency:'EUR':'symbol':'1.2-2' }}</p>

<!-- argument from a component property -->
<p>{{ total | currency:currencyCode }}</p>

Chaining pipes

The output of one pipe can feed straight into another. Angular applies them left to right, which makes it easy to combine transformations.

<p>{{ issued | date:'fullDate' | uppercase }}</p>

Output:

SUNDAY, JUNE 14, 2026

Here date produces a formatted string and uppercase then capitalises it. Read chains as a pipeline: each stage receives the previous stage’s result.

Pipes versus methods

You could format values by calling a method in the template — {{ formatPrice(total) }} — but pipes are usually the better tool. The crucial difference is change detection. A pure pipe (the default) only re-runs when its input reference changes, so Angular skips it on most change-detection cycles. A method, by contrast, has no such guarantee and is re-invoked on every cycle, which can run thousands of times per second.

AspectPipeMethod in template
Re-evaluationOnly when input changes (pure)Every change-detection cycle
CachingBuilt in for pure pipesNone
ReuseImportable across componentsTied to one component
ReadabilityDeclarative value | pipeImperative call
CompositionChainable with |Manual nesting

Avoid calling methods in templates for anything you display repeatedly. A pure pipe gives you the same result with automatic memoisation, so prefer a pipe whenever the transformation depends only on its inputs.

Where pipes can be used

Pipes work anywhere a template expression is evaluated: inside interpolation {{ }} and inside property bindings.

<!-- interpolation -->
<span>{{ score | percent }}</span>

<!-- property binding -->
<input [value]="name | titlecase" />

Pipes cannot be used in the template statements that handle events (the right-hand side of (click)="..."), because those run imperative code rather than producing a displayed value.

Built-in and custom pipes

Angular ships a set of common pipes in @angular/common, including date, currency, number, percent, uppercase, lowercase, titlecase, slice, json, keyvalue, and the special async pipe for observables and promises. When none fits, you can write your own with the @Pipe decorator and a transform method.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'truncate', standalone: true })
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit = 20): string {
    return value.length > limit ? value.slice(0, limit) + '…' : value;
  }
}
<p>{{ description | truncate:10 }}</p>

The first parameter of transform is always the piped value; any further parameters map to the colon-separated arguments in the template.

Best Practices

  • Prefer pipes over template method calls for display formatting, so Angular can cache results and skip needless recomputation.
  • Keep transform logic pure and side-effect free; a pipe should compute output solely from its inputs.
  • Import only the built-in pipes a component actually uses into its imports array for clear, tree-shakeable dependencies.
  • Reach for built-in pipes first (date, currency, number) before writing a custom one — they handle locale and edge cases for you.
  • Use the async pipe to subscribe to observables in the template; it unsubscribes automatically and avoids manual lifecycle code.
  • Be deliberate before marking a pipe impure — it runs on every change-detection cycle and can hurt performance.
Last updated June 14, 2026
Was this helpful?