Angular is known for its clean, declarative templates and powerful data-binding system. One of the most elegant features that enhances template readability is Pipes.
Pipes are a fundamental feature in Angular used for transforming data directly in templates. They help format data before displaying it to the user — without changing the underlying component logic.
In this post, you’ll learn what pipes are, why they are useful, how to use built-in pipes, and how to create custom pipes for your own data transformations.
1. What Are Pipes in Angular?
A pipe in Angular takes in data as input and transforms it into a desired output format for display in the template.
They are defined using the pipe (|
) operator in template expressions.
Example:
<p>{{ title | uppercase }}</p>
If the title
variable contains "angular tutorial"
, the pipe transforms it to "ANGULAR TUTORIAL"
.
In this example, uppercase
is a built-in Angular pipe that converts all characters of a string to uppercase.
2. Why Use Pipes?
Without pipes, you’d have to handle all formatting logic inside the component’s TypeScript file, making your code messy and repetitive.
For example, if you want to display a formatted date or currency in multiple places, you would need helper functions for each transformation.
Pipes eliminate this redundancy by allowing transformations directly in the HTML template, keeping your components clean and focused only on data logic.
Example Without Pipe:
@Component({
selector: 'app-date-example',
template: <p>{{ formattedDate }}</p>
})
export class DateExampleComponent implements OnInit {
formattedDate: string = '';
ngOnInit() {
const date = new Date();
this.formattedDate = date.toDateString();
}
}
Example With Pipe:
<p>{{ today | date:'fullDate' }}</p>
No extra logic is needed in the TypeScript file. Angular’s DatePipe
takes care of formatting automatically.
3. How Pipes Work Under the Hood
When Angular renders a template, it checks for any expressions containing the pipe (|
) operator. The pipe expression has two parts:
- The input data — for example,
title
- The pipe name — for example,
uppercase
Angular executes the pipe’s transformation function during change detection and displays the result.
A single pipe transforms data one way — from model to view. Pipes are pure functions by default, meaning they only re-run when their input data changes.
4. Syntax of a Pipe in a Template
The general syntax is:
{{ value | pipeName:parameter1:parameter2 }}
Example with Multiple Parameters:
<p>{{ price | currency:'USD':'symbol':'1.2-2' }}</p>
Here:
currency
is the pipe name.'USD'
,'symbol'
, and'1.2-2'
are parameters for customization.
5. Types of Pipes in Angular
Angular has two main categories of pipes:
1. Built-in Pipes
Provided by Angular out of the box — such as DatePipe
, CurrencyPipe
, UpperCasePipe
, LowerCasePipe
, PercentPipe
, DecimalPipe
, and AsyncPipe
.
2. Custom Pipes
Created by developers to perform specific transformations that are not available among built-in pipes.
6. Common Built-in Pipes
UpperCasePipe
Converts text to uppercase.
<p>{{ 'angular' | uppercase }}</p>
Output: ANGULAR
LowerCasePipe
Converts text to lowercase.
<p>{{ 'ANGULAR' | lowercase }}</p>
Output: angular
TitleCasePipe
Capitalizes the first letter of each word.
<p>{{ 'learn angular pipes' | titlecase }}</p>
Output: Learn Angular Pipes
DatePipe
Formats date objects or timestamps.
<p>{{ today | date:'fullDate' }}</p>
Output: Wednesday, October 9, 2025
You can use formats like:
'shortDate'
→ 10/9/25'mediumDate'
→ Oct 9, 2025'longDate'
→ October 9, 2025
CurrencyPipe
Formats numbers as currency values.
<p>{{ price | currency:'USD' }}</p>
Output: $99.00
You can customize:
<p>{{ price | currency:'EUR':'symbol':'1.0-0' }}</p>
Output: €99
DecimalPipe
Formats decimal numbers.
<p>{{ 3.14159 | number:'1.2-3' }}</p>
Output: 3.142
PercentPipe
Displays numeric values as percentages.
<p>{{ 0.75 | percent }}</p>
Output: 75%
AsyncPipe
Automatically subscribes to an Observable or Promise and returns the latest emitted value.
<p>{{ userData$ | async }}</p>
It handles subscription and unsubscription automatically, making it ideal for reactive programming.
7. Chaining Multiple Pipes
You can combine multiple pipes to create complex transformations in one line.
Example:
<p>{{ user.name | uppercase | slice:0:10 }}</p>
uppercase
converts the name to uppercase.slice:0:10
limits it to the first 10 characters.
Output: If user.name = 'JonathanDoe'
, the result is JONATHAND
.
8. Using Pipes with Parameters
Many pipes accept parameters to modify their behavior. Parameters are passed after a colon (:
).
Example:
<p>{{ 1234.5678 | number:'1.0-2' }}</p>
Output: 1,234.57
Here:
1.0
→ at least one integer digit.-2
→ up to two decimal places.
9. Creating a Custom Pipe
Angular allows you to create custom pipes using the @Pipe
decorator and implementing the PipeTransform
interface.
Example: Capitalize First Letter Pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'capitalize'
})
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
if (!value) return '';
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
Use it in a component:
<p>{{ 'angular' | capitalize }}</p>
Output: Angular
10. Passing Parameters to a Custom Pipe
You can also make your custom pipes dynamic by accepting arguments.
Example: Repeat Text Pipe
@Pipe({ name: 'repeat' })
export class RepeatPipe implements PipeTransform {
transform(value: string, times: number): string {
return value.repeat(times);
}
}
Usage:
<p>{{ 'Hi ' | repeat:3 }}</p>
Output: Hi Hi Hi
11. Pure vs Impure Pipes
By default, Angular pipes are pure, meaning they execute only when their input changes.
Pure Pipe Example
@Pipe({ name: 'pureExample', pure: true })
Pure pipes are efficient and suitable for most use cases.
Impure Pipe Example
@Pipe({ name: 'impureExample', pure: false })
Impure pipes run on every change detection cycle, which can impact performance.
Use them only when working with mutable objects or collections that frequently change.
12. Example of an Impure Pipe
@Pipe({ name: 'filter', pure: false })
export class FilterPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if (!items || !searchText) return items;
return items.filter(item =>
item.toLowerCase().includes(searchText.toLowerCase())
);
}
}
Template usage:
<li *ngFor="let name of names | filter:searchText">{{ name }}</li>
This pipe filters a list based on user input dynamically.
13. Benefits of Using Pipes
- Cleaner Templates
Pipes allow formatting and transformation directly in templates, avoiding clutter in TypeScript files. - Reusability
A pipe can be used in multiple components throughout the app. - Separation of Concerns
Data logic stays in pipes, while UI logic remains in components. - Improved Readability
Templates are easier to read and maintain when transformation logic is simplified using pipes.
14. When Not to Use Pipes
Avoid using pipes when:
- The transformation is complex or computationally heavy.
- You’re modifying large data sets frequently (e.g., filtering big arrays).
- You need backend-side transformations (pipes are only for display, not actual data manipulation).
For large operations, perform transformations in the component or service layer.
15. Using Pipes in Components and Modules
Every pipe must be declared in an Angular module before it can be used.
Example:
@NgModule({
declarations: [
AppComponent,
CapitalizePipe,
RepeatPipe
],
bootstrap: [AppComponent]
})
export class AppModule {}
16. AsyncPipe in Depth
AsyncPipe
is one of the most powerful Angular pipes. It automatically handles Observables and Promises.
Example with Observable:
@Component({
selector: 'app-users',
template: `
<ul>
<li *ngFor="let user of users$ | async">{{ user.name }}</li>
</ul>
`
})
export class UsersComponent {
users$ = this.http.get<any[]>('https://jsonplaceholder.typicode.com/users');
constructor(private http: HttpClient) {}
}
The AsyncPipe
eliminates the need for manual subscribe()
and unsubscribe()
calls.
17. Combining Pipes for Custom Output
You can chain pipes to create powerful transformations.
Example:
<p>{{ 'angular pipes tutorial' | titlecase | slice:0:15 }}</p>
First, the text is transformed to Angular Pipes Tutorial
, and then truncated to the first 15 characters:Angular Pipes T
18. Pipe Performance Considerations
- Pure pipes are cached and optimized.
- Impure pipes can slow down performance because they run frequently.
- Avoid using impure pipes on large lists or inside
*ngFor
loops.
If a pipe causes performance issues, consider using memoization or performing transformations in the component instead.
19. Testing a Pipe
Testing ensures your pipes work as expected.
Example:
import { CapitalizePipe } from './capitalize.pipe';
describe('CapitalizePipe', () => {
const pipe = new CapitalizePipe();
it('transforms "angular" to "Angular"', () => {
expect(pipe.transform('angular')).toBe('Angular');
});
it('returns empty string for null input', () => {
expect(pipe.transform(null as any)).toBe('');
});
});
20. Real-World Example: Formatting User Data
Imagine you have a user list and want to display names in title case, registration dates formatted, and balance in currency.
Component Template:
<div *ngFor="let user of users">
<p>{{ user.name | titlecase }}</p>
<p>{{ user.registered | date:'mediumDate' }}</p>
<p>{{ user.balance | currency:'USD' }}</p>
</div>
The pipes handle all data transformations elegantly, without extra logic in the TypeScript class.
21. Global vs Local Pipes
Pipes can be used globally (declared in the root module) or locally (declared in a feature module).
If a pipe is used only in one feature module, declare it locally to avoid unnecessary imports in other parts of the app.
22. Localization Support in Pipes
Angular pipes like CurrencyPipe
, DatePipe
, and DecimalPipe
are locale-aware. You can configure localization by setting the locale in your app module.
Example:
import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';
registerLocaleData(localeFr);
This ensures your dates, currencies, and numbers format according to French locale settings.
23. Reusable Utility Pipes
You can create reusable utility pipes like:
TruncatePipe
→ shorten long textFilterPipe
→ filter listsSortPipe
→ sort arraysSearchPipe
→ search text within data
These small reusable pipes enhance productivity across large applications.
Leave a Reply