Skip to content

Angular Pipes

Pipes transform a value for display directly inside a template, without changing the underlying data. This lesson covers Angular's built-in pipes and how to use them effectively.

What Is a Pipe?

A pipe takes an input value and transforms it into a display-ready output, formatting a date, converting a number to currency, or converting text to uppercase, using the | (pipe) operator directly in a template expression.

Pipes keep formatting logic out of the component class and out of the template's raw expression, making views easier to read and formatting logic reusable across the whole application.

<p>{{ order.total | currency }}</p>
<p>{{ order.placedAt | date:'medium' }}</p>
<p>{{ user.name | uppercase }}</p>

Each pipe transforms its input for display only, order.total itself remains an untouched number in the component class.

Pipe Syntax

{{ value | pipeName }}
{{ value | pipeName:arg1 }}
{{ value | pipeName:arg1:arg2 }}
{{ value | pipe1 | pipe2 }}
  • The pipe operator | sits between the value and the pipe name inside an interpolation expression.
  • Arguments are passed after a colon, and multiple arguments are separated by additional colons.
  • Pipes can be chained, output of one becomes input to the next, left to right.
  • Standalone components must import the specific pipe (like DatePipe) they use.

Built-in Angular Pipes Cheatsheet

The pipes you will use most often for formatting data in templates.

Pipe Example Output
date {{ today | date:'shortDate' }} 1/1/26
currency {{ 24.5 | currency }} $24.50
percent {{ 0.42 | percent }} 42%
decimal {{ 3.14159 | number:'1.2-2' }} 3.14
uppercase {{ 'abc' | uppercase }} ABC
lowercase {{ 'ABC' | lowercase }} abc
titlecase {{ 'hello world' | titlecase }} Hello World
json {{ data | json }} Pretty-printed JSON string
slice {{ items | slice:0:3 }} First 3 items
async {{ data$ | async }} Latest value from an Observable/Promise

Pipes With Parameters

Many built-in pipes accept parameters that refine their output, a currency code for currency, a format string for date, or a digit range for number.

{{ price | currency:'EUR' }}
{{ event.date | date:'EEEE, MMMM d, y' }}
{{ pi | number:'1.0-3' }}

number:'1.0-3' means: minimum 1 integer digit, 0 minimum and 3 maximum decimal digits.

Chaining Multiple Pipes

Pipes can be chained left to right; the output of the first pipe becomes the input to the next, useful for combining transformations like uppercasing and truncating text.

<p>{{ product.name | uppercase | slice:0:20 }}</p>

Pure vs Impure Pipes

By default, pipes are pure: Angular only re-runs them when the input reference changes, not on every change detection cycle, which is efficient but means mutating an array or object in place won't trigger a pure pipe to re-run. Impure pipes (pure: false) re-run on every check, which is more expensive but sometimes necessary.

@Pipe({ name: 'appFilter', standalone: true, pure: false })
export class FilterPipe implements PipeTransform {
  transform(items: unknown[], predicate: (item: unknown) => boolean) {
    return items.filter(predicate);
  }
}

The built-in async pipe is a notable, carefully implemented impure pipe, it needs to react to new emitted values over time.

Common Mistakes

  • Forgetting to import a specific built-in pipe (like DatePipe) in a standalone component's imports array.
  • Mutating an array in place and expecting a pure pipe to detect the change and re-run.
  • Writing expensive filtering/sorting logic as an impure pipe that runs on every change detection cycle.
  • Formatting dates and currency manually in the component class instead of using the built-in date/currency pipes.

Key Takeaways

  • Pipes transform a value for display using the | operator without mutating the original data.
  • Angular ships built-in pipes for dates, numbers, currency, text casing, JSON, and async values.
  • Pipes can accept parameters and be chained together left to right.
  • Pure pipes (the default) only re-run when their input reference changes; impure pipes re-run every check.

Pro Tip

Avoid array filtering/sorting pipes for large lists; they re-run on every input reference change and can be a performance trap. Filter or sort the data once in the component (or with a memoized signal/computed) instead.