Introduction
Angular provides several built-in pipes such as DatePipe, CurrencyPipe, UpperCasePipe, and AsyncPipe that help developers transform data directly in templates. But sometimes require custom formatting, so we need to create a custom pipe.
A custom pipe lets you create your own reusable data transformation logic and reuse it across multiple components. Instead of writing the same formatting code repeatedly, you can encapsulate it in a pipe and apply it using Angular’s familiar pipe (|) syntax.
For example, suppose you want to reverse a string.
Input:
Angular
Output:
Note: Instead of writing this logic inside every component, you can create a reusable custom pipe and use it anywhere in your application.
Why Use Custom Pipes?
Custom pipes offer several important benefits.
1. Reusability
Once created, a custom pipe can be used in multiple components without duplicating code.
2. Cleaner Templates
Instead of calling formatting methods repeatedly, templates remain simple and easy to understand.
Example:
{{ username | reverse }}
is much cleaner than:
{{ reverseString(username) }}
3. Separation of Concerns
Components focus on application logic, while pipes handle presentation-related transformations.
4. Easier Maintenance
When formatting rules change, you update only the pipe, not every component.
5. Better Readability
Templates become more expressive because the transformation is visible directly in the markup.
Creating a Custom Pipe
Angular CLI makes creating a pipe simple.
Run the following command:
Syntax:
ng generate pipe pipeName
Or use the shorter version:
ng g p pipeName
Example:
ng generate pipe reverse
Or use the shorter version:
ng g p reverse
Angular automatically creates:
reverse.pipe.ts
reverse.pipe.spec.ts
The .pipe.ts file contains the implementation, while the .spec.ts file is used for unit testing.
Structure of a Custom Pipe
A custom pipe is a TypeScript class decorated with @Pipe.
Example:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'reverse'
})
export class ReversePipe implements PipeTransform {
transform(value: string): string {
return value.split('').reverse().join('');
}
}
Understanding the Code
- @Pipe marks the class as an Angular pipe.
- name defines how the pipe is used inside templates.
- PipeTransform is an interface that requires the transform() method.
- transform() contains the logic that converts the input into the desired output.
Using a Custom Pipe
Once the pipe is available in your application, it can be used just like a built-in pipe.
Component:
title = 'Angular';
Template:
<p>{{ title | reverse }}<p>
Output:
The original value remains unchanged; only the displayed output is transformed.
The transform() Method
Every custom pipe must implement the transform() method.
Basic syntax:
transform(value: any): any
Note: The first parameter is the value being transformed.
Example:
transform(value: string): string {
return value.toUpperCase();
}
Angular automatically passes the template value to the method.
Passing Parameters to Custom Pipes
Custom pipes can accept one or more parameters.
Example:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'truncate'
})
export class TruncatePipe implements PipeTransform {
transform(value: string, length: number): string {
if (!value) {
return '';
}
if (value.length <= length) {
return value;
}
return value.substring(0, length) + '...';
}
}
Usage:
{{ description | truncate:20 }}
Output:
The number after the colon (:) is passed as the second argument to the transform() method.
Multiple Parameters
A pipe can accept multiple parameters.
Example:
transform(value: string, start: number, end: number): string {
return value.substring(start, end);
}
Usage:
{{ title | customSlice:0:5 }}
Angular passes each parameter in the order they appear.
Standalone Custom Pipes in Angular 20+
Angular 20 encourages standalone APIs.
A standalone custom pipe is created by setting:
import{ Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'reverse',
standalone: true
})
export class ReversePipe implements PipeTransform {
transform(value: string): string {
return value.split('').reverse().join('');
}
}
The pipe can then be imported directly into a standalone component.
Example:
import { Component } from '@angular/core';
import { ReversePipe } from './reverse.pipe';
@Component({
selector: 'app-home',
standalone: true,
imports: [ReversePipe],
template: `
<h2>{{ 'Angular' | reverse }}<h2>
`
})
export class HomeComponent {}
This eliminates the need to declare the pipe inside an NgModule, reducing boilerplate.
Pure vs. Impure Custom Pipes
Angular custom pipes can be either pure or impure.
Pure Pipes
Pure pipes execute only when Angular detects a change in the input value or object reference.
Example:
@Pipe({
name: 'capitalize',
pure: true
})
Pure pipes are the default and are recommended for most scenarios because they offer better performance.
Impure Pipes
Impure pipes execute during every Angular change detection cycle.
Example:
@Pipe({
name: 'filter',
pure: false
})
Impure pipes are useful when working with mutable arrays or objects but should be used sparingly because they can negatively affect performance.
Real-World Custom Pipe Examples
1. Masking Sensitive Data
A custom pipe can hide part of an email or phone number.
Example:
Input:
john@example.com
Output:
This is useful in banking, healthcare, and e-commerce applications.
2. Capitalizing the First Letter
Instead of converting every word to title case, you might only want to capitalize the first character.
Input:
angular
Output:
3. Shortening Long Text
Blog posts, product descriptions, and comments often need truncation.
Input:
Angular is a modern web application framework.
Output:
4. Phone Number Formatting
Input:
9876543210
Output:
5. File Size Formatting
Input:
1536000
Output:
Such transformations make data easier for users to read without modifying the underlying values.
Best Practices
Follow these recommendations when creating Angular custom pipes.
1. Keep Pipes Focused
Each pipe should perform one specific transformation.
Avoid combining multiple unrelated tasks in a single pipe.
2. Use Pure Pipes Whenever Possible
Pure pipes execute less frequently and provide better performance.
Only use impure pipes when necessary.
3. Avoid Heavy Computation
Pipes should not perform expensive calculations, API requests, or database operations.
Heavy business logic belongs in services.
4. Return Consistent Types
A pipe should consistently return the expected data type to prevent unexpected behavior in templates.
5. Use Strong Typing
Avoid any whenever possible.
Example:
transform(value: string): string
Strong typing improves readability and catches errors during development.
6. Write Unit Tests
Angular CLI automatically generates a .spec.ts file for each pipe.
Testing custom pipes ensures they behave correctly for various inputs and edge cases.
Common Mistakes
Developers often make these mistakes when creating custom pipes.
1. Performing Business Logic
Custom pipes should transform displayed data only.
Business rules and application workflows belong in services or components.
2. Creating Too Many Impure Pipes
Impure pipes execute frequently, which can reduce application performance if overused.
3. Returning Different Data Types
Returning a string in one case and an object in another can make templates difficult to understand and debug.
Ignoring Null or Undefined Values
Always check for invalid input to prevent runtime errors.
Example:
if (!value) {
return '';
}
This simple check improves the reliability of your pipe.
Advantages and Disadvantages
Advantages
- Encourages reusable code
- Simplifies templates
- Improves readability
- Separates presentation logic from business logic
- Reduces duplicate formatting code
- Easy to test
- Works seamlessly with standalone components
- Easy to maintain
Disadvantages
- Impure pipes may affect performance
- Pipes are limited to data transformation
- Poorly designed pipes can become difficult to maintain
- Complex business logic should not be placed inside pipes
When used correctly, custom pipes are lightweight, reusable, and highly effective.
Conclusion
Angular custom pipes provide a powerful way to create reusable data transformations that keep templates clean and components focused on business logic.
Angular 20+ further enhances the developer experience by supporting standalone pipes, allowing them to be imported directly into standalone components without requiring an NgModule.
Angular Custom Pipe – Objective Questions (MCQs)
Q1. Custom pipes are created using:
Q2. Custom pipe must implement:
Q3. transform() method returns:
Q4. Custom pipes are used for:
Q5. Custom pipes are declared in: