Custom Pipes

Build Your Own Reusable Template Transform

Custom Pipes

A pipe is a class decorated with @Pipe that implements a transform method — the smallest reusable unit in an Angular template.

4 min read Level 2/5 #angular#templates#pipes
What you'll learn
  • Create a class with @Pipe
  • Implement the transform method
  • Use the pipe inside a standalone component

When none of the built-in pipes fit, write your own. The API is tiny and the result reads beautifully in templates.

The Shape of a Pipe

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

@Pipe({
  name: 'truncate',
  standalone: true,
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, max: number = 30, suffix: string = '…'): string {
    if (!value) return '';
    return value.length > max ? value.slice(0, max) + suffix : value;
  }
}

Three pieces:

  • The @Pipe decorator with a name (what you type in the template).
  • standalone: true so it works without an NgModule.
  • A transform method whose first argument is the piped value; the rest are pipe arguments.

Using It

import { Component } from '@angular/core';
import { TruncatePipe } from './truncate.pipe';

@Component({
  selector: 'app-post',
  standalone: true,
  imports: [TruncatePipe],
  template: `
    <h3>{{ title | truncate:20 }}</h3>
    <p>{{ body | truncate:140:' [more]' }}</p>
  `,
})
export class PostComponent {
  title = 'A Tale of Two Components';
  body = 'It was the best of code, it was the worst of code…';
}

Pure vs Impure

By default a pipe is pure: Angular calls transform only when the input reference changes. That makes pipes cheap.

If your pipe needs to react to deeper mutations (rare, and usually a sign of a refactor), opt in to impure:

@Pipe({ name: 'sortBy', standalone: true, pure: false })

Impure pipes run on every change-detection tick. Use them sparingly and only when no computed() signal will do.

Typing the Transform

Make the input and output generic to keep autocomplete sharp:

@Pipe({ name: 'pluck', standalone: true })
export class PluckPipe implements PipeTransform {
  transform<T, K extends keyof T>(items: T[], key: K): T[K][] {
    return items.map(i => i[key]);
  }
}
Template Reference Variables →