Angular Pipes
Pipes are a feature in Angular that transform data before it is displayed in the template. A pipe takes a value as input and returns a formatted version of that value as output. The original data in the TypeScript class is not changed — only the way it appears on the screen is transformed.
Pipes are used directly inside Angular templates with the pipe symbol |. The syntax reads naturally: "take this value | and transform it using this pipe."
A real-world analogy: a pipe in plumbing takes water in and delivers it in a different form (filtered, heated, or pressurized). Angular pipes take data in and deliver it in a different display format.
Why Use Pipes?
Without pipes, display formatting would require extra logic inside the TypeScript class. For example, converting a number to a currency format, capitalizing a string, or formatting a date would need extra code every time. Pipes handle this cleanly and reusably inside the template itself.
Built-in Pipes
Angular includes several built-in pipes for the most common formatting tasks. These are available in any template without any additional setup.
DatePipe — Formatting Dates
The date pipe formats a date value into a human-readable string.
// date-demo.component.ts
export class DateDemoComponent {
today = new Date();
launchDate = new Date('2024-03-15');
timestamp = 1710460800000; // Unix timestamp in milliseconds
}
<!-- date-demo.component.html -->
<p>{{ today | date }}</p> <!-- Mar 15, 2024 -->
<p>{{ today | date:'fullDate' }}</p> <!-- Friday, March 15, 2024 -->
<p>{{ today | date:'shortDate' }}</p> <!-- 3/15/24 -->
<p>{{ today | date:'dd/MM/yyyy' }}</p> <!-- 15/03/2024 -->
<p>{{ today | date:'hh:mm a' }}</p> <!-- 09:30 AM -->
<p>{{ today | date:'dd-MMM-yyyy HH:mm' }}</p> <!-- 15-Mar-2024 09:30 -->
CurrencyPipe — Formatting Currency
The currency pipe formats a number as a monetary value with the correct currency symbol.
export class PriceComponent {
productPrice = 1499.99;
discount = 0.2;
}
<p>{{ productPrice | currency }}</p> <!-- $1,499.99 -->
<p>{{ productPrice | currency:'EUR' }}</p> <!-- €1,499.99 -->
<p>{{ productPrice | currency:'GBP':'symbol' }}</p> <!-- £1,499.99 -->
<p>{{ productPrice | currency:'INR':'symbol':'1.0-0' }}</p> <!-- ₹1,500 -->
DecimalPipe — Formatting Numbers
The number pipe formats numeric values with specified decimal places and thousands separators.
The format string follows this pattern: minIntegerDigits.minFractionDigits-maxFractionDigits
export class NumberComponent {
population = 1382000000;
pi = 3.14159265;
rating = 4.7;
}
<p>{{ population | number }}</p> <!-- 1,382,000,000 -->
<p>{{ pi | number:'1.2-4' }}</p> <!-- 3.1416 -->
<p>{{ rating | number:'1.1-1' }}</p> <!-- 4.7 -->
<p>{{ 0.75 | percent }}</p> <!-- 75% -->
<p>{{ 0.75 | percent:'1.1-2' }}</p> <!-- 75.0% -->
UpperCasePipe and LowerCasePipe — Text Case
export class TextComponent {
title = 'Angular Tutorial';
code = 'APP-COMPONENT';
}
<p>{{ title | uppercase }}</p> <!-- ANGULAR TUTORIAL -->
<p>{{ code | lowercase }}</p> <!-- app-component -->
<p>{{ title | titlecase }}</p> <!-- Angular Tutorial -->
SlicePipe — Extracting Parts of a String or Array
The slice pipe extracts a portion of a string or array using start and end index positions.
export class SliceComponent {
fullText = 'Angular is a powerful framework for building web applications';
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
}
<p>{{ fullText | slice:0:30 }}...</p> <!-- Angular is a powerful fram... -->
<p>{{ numbers | slice:0:5 }}</p> <!-- 1,2,3,4,5 -->
<p>{{ numbers | slice:5 }}</p> <!-- 6,7,8,9,10 -->
JsonPipe — Displaying Objects for Debugging
The json pipe converts a JavaScript object into a readable JSON string. It is extremely useful during development to inspect the contents of an object directly in the browser.
export class DebugComponent {
user = { name: 'Alex', age: 28, role: 'Admin' };
}
<pre>{{ user | json }}</pre>
Output:
{
"name": "Alex",
"age": 28,
"role": "Admin"
}
AsyncPipe — Handling Observables and Promises
The async pipe subscribes to an Observable or Promise and automatically displays its latest value. When the component is destroyed, the async pipe unsubscribes automatically, preventing memory leaks.
// data.component.ts
import { Component } from '@angular/core';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';
export class DataComponent {
// Simulates data arriving after a 2-second delay
data$: Observable<string> = of('Data loaded successfully!').pipe(delay(2000));
}
<!-- data.component.html -->
<p>{{ data$ | async }}</p>
<!-- Displays nothing for 2 seconds, then shows: Data loaded successfully! -->
Chaining Multiple Pipes
Multiple pipes can be chained together. The output of the first pipe becomes the input of the second pipe.
export class ChainComponent {
announcement = 'new product launch on friday';
releaseDate = new Date('2024-06-01');
}
<p>{{ announcement | titlecase | slice:0:20 }}...</p>
<!-- First applies titlecase: "New Product Launch On Friday" -->
<!-- Then slices to 20 chars: "New Product Launch O..." -->
<p>{{ releaseDate | date:'fullDate' | uppercase }}</p>
<!-- First formats date: "Saturday, June 1, 2024" -->
<!-- Then uppercases: "SATURDAY, JUNE 1, 2024" -->
Creating a Custom Pipe
When the built-in pipes do not cover a specific formatting need, a custom pipe can be created using the Angular CLI:
ng generate pipe pipes/truncate
This creates a pipe that shortens text to a specified maximum length and adds "..." at the end:
// truncate.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'truncate'
})
export class TruncatePipe implements PipeTransform {
transform(value: string, maxLength: number = 50): string {
if (!value) return '';
if (value.length <= maxLength) return value;
return value.substring(0, maxLength) + '...';
}
}
<!-- Using the custom truncate pipe -->
<p>{{ 'This is a very long description that should be truncated at some point' | truncate:30 }}</p>
<!-- Output: This is a very long descript... -->
<p>{{ 'Short text' | truncate:30 }}</p>
<!-- Output: Short text (no truncation, length is under 30) -->
The @Pipe decorator defines the pipe's name — the name used in the template. The transform method receives the input value and any additional arguments (passed after the colon : in the template).
Pure vs Impure Pipes
Pure Pipes (Default)
By default, all Angular pipes are pure. A pure pipe runs the transform method only when its input value changes. If the same value is passed in, the pipe returns the cached result instead of re-running. This is efficient for performance.
Impure Pipes
An impure pipe runs the transform method on every change detection cycle, regardless of whether the input changed. This is necessary when the pipe needs to detect changes inside objects or arrays. Impure pipes can impact performance and should be used carefully.
@Pipe({
name: 'filterList',
pure: false // Mark as impure to detect array mutations
})
Summary
Pipes transform data for display inside Angular templates using the | syntax. Angular includes built-in pipes for dates (date), currency (currency), numbers (number, percent), text (uppercase, lowercase, titlecase), array slicing (slice), JSON display (json), and async values (async). Multiple pipes can be chained. Custom pipes are created with the @Pipe decorator and must implement the PipeTransform interface with a transform method. Pure pipes (the default) only re-run when input changes, making them efficient. Impure pipes re-run on every change detection cycle.
