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.
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
@Pipedecorator with aname(what you type in the template). standalone: trueso it works without an NgModule.- A
transformmethod 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]);
}
}