Angular  

Beginner’s Guide to Angular Pipes (Built-in and Custom) — With Practical Examples

Angular Pipes allow you to transform data directly in templates without writing extra TypeScript logic.
They make your templates clean, readable, and professional.

This guide explains what pipes are, how to use built-in pipes, how to build custom pipes, and when to apply them in real Angular apps.

Structured for complete beginners but written with production accuracy.

What Are Angular Pipes?

A Pipe is a simple function that:

  • Takes input

  • Transforms the value

  • Returns formatted output

They are used in HTML templates using the pipe operator |.

Example

{{ today | date }}

If today = new Date(), Angular prints a formatted date.

Why Use Pipes?

Benefits:

  1. Format data without writing TypeScript code

  2. Keep HTML clean and readable

  3. Reuse formatting logic across the app

  4. Build custom formatting rules for your domain

Types of Angular Pipes

A. Built-in Pipes

Provided by Angular (date, currency, uppercase, async, etc.)

B. Custom Pipes

Pipes you create for custom formatting (status format, masking, unit conversion, etc.)

Built-in Angular Pipes (With Easy Examples)

Below are the most commonly used pipes.

Date Pipe

{{ today | date:'dd/MM/yyyy' }}

Output example: 12/02/2025

Uppercase / Lowercase Pipe

{{ name | uppercase }}
{{ name | lowercase }}

Currency Pipe

{{ amount | currency:'INR' }}

Output: ₹5,000.00

Decimal Pipe

{{ price | number:'1.2-2' }}

Meaning:

  • Minimum 1 digit before decimal

  • Minimum 2 digits after decimal

  • Maximum 2 digits after decimal

Percent Pipe

{{ score | percent }}

If score = 0.93, output → 93%

Slice Pipe

Useful for pagination, trimming lists, etc.

{{ message | slice:0:10 }}

JSON Pipe

Useful for debugging.

<pre>{{ user | json }}</pre>

Async Pipe

Used with Observables or Promises.

<div *ngIf="data$ | async as data">
  {{ data.name }}
</div>

Async pipe handles subscribing and unsubscribing automatically.

Built-In Pipes in Real Project Example

<div *ngFor="let order of orders">
  <p>Order ID: {{ order.id }}</p>
  <p>Total: {{ order.total | currency:'INR' }}</p>
  <p>Created: {{ order.createdOn | date:'medium' }}</p>
  <p>Status: {{ order.status | uppercase }}</p>
</div>

Professional and readable.

Creating Custom Pipes (Step-by-Step)

Sometimes built-in pipes are not enough.
You might need:

  • Masking phone numbers

  • Formatting status text

  • Custom date formats

  • Converting units (kg to g, seconds to minutes)

Let’s create one.

Step 1: Generate Pipe

ng generate pipe status

Angular creates:

  • status.pipe.ts

  • status.pipe.spec.ts

Step 2: Write Logic

status.pipe.ts

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

@Pipe({
  name: 'status'
})
export class StatusPipe implements PipeTransform {

  transform(value: number): string {
    switch (value) {
      case 1: return 'Active';
      case 0: return 'Inactive';
      case 2: return 'Pending Approval';
      default: return 'Unknown';
    }
  }
}

Step 3: Use in Template

<p>User Status: {{ user.status | status }}</p>

If user.status = 1,
Output → Active

More Custom Pipe Examples

Percentage Formatter Pipe

@Pipe({ name: 'percentFixed' })
export class PercentFixedPipe implements PipeTransform {
  transform(value: number, decimals: number = 2): string {
    return (value * 100).toFixed(decimals) + '%';
  }
}

Usage:

{{ 0.8732 | percentFixed:1 }}

Output: 87.3%

Mask Phone Number

@Pipe({ name: 'maskPhone' })
export class MaskPhonePipe implements PipeTransform {
  transform(value: string): string {
    return value.slice(0, 2) + '******' + value.slice(-2);
  }
}

Usage:

{{ '9876543210' | maskPhone }}

Output: 98******10

File Size Pipe (Bytes → KB → MB)

Used in upload screens

@Pipe({ name: 'fileSize' })
export class FileSizePipe implements PipeTransform {

  transform(bytes: number): string {
    if (bytes < 1024) return bytes + ' B';
    const kb = bytes / 1024;
    if (kb < 1024) return kb.toFixed(2) + ' KB';
    const mb = kb / 1024;
    return mb.toFixed(2) + ' MB';
  }
}

Usage:

{{ file.size | fileSize }}

Pure vs Impure Pipes (Important for Performance)

Pure Pipe (default)

Runs only when input changes.

Ideal for:

  • currency

  • uppercase

  • custom formatters

Impure Pipe

@Pipe({
  name: 'filterUsers',
  pure: false
})

Runs on every change detection cycle.
Use only when necessary (dynamic arrays, filtering while typing).

Impure pipes can slow your app.

Best Practices for Pipes

  1. Keep pipes simple.

  2. Prefer pure pipes for performance.

  3. Do not write heavy computations inside pipes.

  4. For filtering or sorting large lists, use services.

  5. Do not call API inside a pipe.

  6. Use async pipe for Observables instead of manual subscribe().

Real Case Study: Using Pipes in an Angular Dashboard

Scenario

You are building an admin dashboard showing:

  • Date

  • Order amount

  • Status

  • User details

Template

<tr *ngFor="let order of orders">
  <td>{{ order.date | date:'short' }}</td>
  <td>{{ order.amount | currency:'INR' }}</td>
  <td>{{ order.status | status }}</td>
  <td>{{ order.userPhone | maskPhone }}</td>
  <td>{{ order.fileSize | fileSize }}</td>
</tr>

This makes your template readable, clean, and production-ready.

Conclusion

Angular Pipes are one of the simplest yet most powerful features in Angular.
They help you:

  • Format data

  • Reduce TypeScript code

  • Improve readability

  • Build reusable transformation logic

With built-in pipes + custom pipes, you can handle almost any UI formatting need.