#angular #pipes #formatting #transform

Day 10 — Angular Pipes: Formatting, Transforming & Custom Pipes

📘 Day 10 — Angular Pipes: Formatting, Transforming & Custom Pipes

Zero to Hero — Hands-on Angular Tutorial

Today you will learn:

  • ✔️ What are Pipes (|)?
  • ✔️ Using Built-in Pipes (Date, Currency, JSON, TitleCase)
  • ✔️ Parameterizing & Chaining Pipes
  • ✔️ The AsyncPipe (and when to use it)
  • ✔️ Creating Custom Pipes (e.g., Truncate, RelativeTime)
  • ✔️ Pure vs. Impure Pipes (Performance)

Pipes are Angular’s elegantly simple way to transform data right in the template. ✨


🟦 1. What is a Pipe?

A pipe takes data as input and transforms it to a desired output for display. It does not change the actual data in your TypeScript class, only how it looks to the user.

Syntax:

{{ value | pipeName }}

🟩 2. Essential Built-in Pipes

Angular comes with batteries included.

📅 DatePipe

Formats standard JavaScript dates.

<p>{{ today | date }}</p>            <!-- Dec 10, 2025 -->
<p>{{ today | date:'short' }}</p>    <!-- 12/10/25, 2:30 PM -->
<p>{{ today | date:'fullDate' }}</p> <!-- Wednesday, December 10, 2025 -->
<p>{{ today | date:'yyyy-MM-dd' }}</p> <!-- 2025-12-10 -->

💰 CurrencyPipe

Automatically handles symbols and decimals.

<p>{{ 1234.5 | currency }}</p>          <!-- $1,234.50 -->
<p>{{ 1234.5 | currency:'EUR' }}</p>    <!-- €1,234.50 -->
<p>{{ 1234.5 | currency:'GBP':'code' }}</p> <!-- GBP 1,234.50 -->

🔠 Text Pipes

<p>{{ 'hello world' | uppercase }}</p>   <!-- HELLO WORLD -->
<p>{{ 'HELLO WORLD' | lowercase }}</p>   <!-- hello world -->
<p>{{ 'angular is cool' | titlecase }}</p> <!-- Angular Is Cool -->

🔍 JsonPipe (The Debugger’s Best Friend)

Dumps an object as a string.

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

🟧 3. Creating Your First Custom Pipe

Let’s build a TruncatePipe to shorten long text (e.g., description previews).

Generate:

ng g pipe pipes/truncate --standalone

Code: truncate.pipe.ts

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

@Pipe({
  name: 'truncate',
  standalone: true
})
export class TruncatePipe implements PipeTransform {

  transform(value: string, limit: number = 20, ellipsis: string = '...'): string {
    if (!value) return '';
    
    if (value.length <= limit) {
      return value;
    }

    return value.slice(0, limit) + ellipsis;
  }
}

Usage:

Import it into your component first!

<p>{{ 'This is a very long description that needs cutting' | truncate:10 }}</p>
<!-- Output: This is a ... -->

<p>{{ 'Short text' | truncate:50 }}</p> 
<!-- Output: Short text -->

🟥 4. Advanced: Relative Time Pipe (“5 mins ago”)

This is a classic feature in social apps.

Generate:

ng g pipe pipes/time-ago --standalone

Code: time-ago.pipe.ts

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

@Pipe({
  name: 'timeAgo',
  standalone: true
})
export class TimeAgoPipe implements PipeTransform {
  transform(value: Date | string): string {
    if (!value) return '';
    
    const date = new Date(value);
    const now = new Date();
    const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);

    if (seconds < 60) return 'Just now';
    
    const minutes = Math.floor(seconds / 60);
    if (minutes < 60) return `${minutes} mins ago`;

    const hours = Math.floor(minutes / 60);
    if (hours < 24) return `${hours} hours ago`;

    const days = Math.floor(hours / 24);
    return `${days} days ago`;
  }
}

Usage:

<p>Posted: {{ postDate | timeAgo }}</p>
<!-- Posted: 3 hours ago -->

🟫 5. Pure vs. Impure Pipes (Performance Warning ⚠️)

By default, pipes are Pure.

  • They only run if the input value changes (e.g., string update).
  • This is super fast.

If you set pure: false:

  • The pipe runs on every single change detection cycle (every mouse move, keypress, etc.).
  • Avoid Impure Pipes unless absolutely necessary (like filtering arrays in place).

Bad Practice: Using pipes for Filtering/Sorting lists. Better Practice: Compute filtered lists in the Component (using Signals computed()).


🟦 6. The AsyncPipe (RxJS Helper)

Even though we use Signals mostly, you will encounter Observables (RxJS). The async pipe subscribes and unsubscribes automatically.

// Component
time$ = interval(1000); // Observable emitting every second
<!-- Template -->
<p>Timer: {{ time$ | async }}</p>
  • ✔️ No memory leaks (unsubscribe handled auto-magically)
  • ✔️ Clean template syntax

🎉 End of Day 10 — What You Learned

Today you added “Data Transformation” to your toolkit:

  • ✔️ Built-in formatting (Date, Currency, JSON)
  • ✔️ Chaining syntax (value | upper | truncate)
  • ✔️ Custom Pipes (Truncate, TimeAgo)
  • ✔️ Performance (Why filtering pipes are risky)

Your UI is now not just functional, but polished.


🧪 Day 10 Challenge

Build a “Credit Card Mask” Pipe.

Requirements:

  1. Create CreditCardPipe.
  2. Input: 1234567812345678
  3. Output: **** **** **** 5678
  4. Handle formatting (add spaces every 4 digits).
  5. Apply it to a list of mock transactions.