Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

Angular Pipes Built in Custom Pipes: Tutorial, Examples, FAQs & Interview Tips

What are Pipes in Angular?

Pipes are a simple and expressive way to transform values directly inside Angular templates. They take a value as input, apply some formatting or transformation, and return the result for display. Pipes are used with the pipe operator |. Instead of changing the original data in the component class, a pipe changes how the value appears in the UI. This makes templates easier to read and keeps presentation-specific formatting logic close to where the value is displayed.

For example, a component may store a raw date object, an unformatted price, a lowercase name, or a long block of text. Pipes let the template decide how those values should be shown to the user. A date can be formatted, a number can be displayed as currency, text can be converted to uppercase, or a long sentence can be shortened. This is one of the reasons pipes are so common in Angular applications: they improve readability while reducing repeated display logic.

Why Pipes Are Useful

  • Cleaner templates by avoiding repeated formatting code in the component.
  • Reusable display logic because the same pipe can be used in many templates.
  • Better separation of concerns because presentation formatting stays separate from business logic.
  • Readable templates since a pipe often explains intent clearly, such as currency, date, or uppercase.
  • Built-in convenience because Angular already ships with many common transformation pipes.

Basic Pipe Syntax

The general syntax looks like this:

Pipe Syntax
{{ value | pipeName }}

If the pipe needs additional options, those are passed using : after the pipe name.

Pipe with Parameters
{{ price | currency:'USD':'symbol':'1.2-2' }}

Multiple pipes can also be chained together. The output of one pipe becomes the input of the next pipe.

Chained Pipes
{{ name | uppercase | slice:0:5 }}

Built-in Pipes

Angular includes several built-in pipes that solve common presentation needs without extra code. These are often the first pipes beginners use.

PipePurposeExample
DatePipeFormats date values{{ today | date:'dd/MM/yyyy' }}
UpperCasePipeConverts text to uppercase{{ name | uppercase }}
LowerCasePipeConverts text to lowercase{{ name | lowercase }}
TitleCasePipeCapitalizes words{{ title | titlecase }}
CurrencyPipeFormats numbers as currency{{ price | currency:'USD' }}
DecimalPipeFormats decimal precision{{ pi | number:'1.2-4' }}
PercentPipeFormats numbers as percentages{{ ratio | percent }}
JsonPipeDisplays objects as JSON{{ data | json }}
SlicePipeSlices strings or arrays{{ items | slice:0:3 }}
AsyncPipeSubscribes to Promises or Observables{{ user$ | async }}
KeyValuePipeTurns object properties into iterable key-value pairs@for (item of obj | keyvalue; track item.key)

Using Built-in Pipes in a Component

When using standalone Angular components, built-in pipes usually need to be imported into the component. The example below shows common pipe usage in one place.

Built-in Pipes Usage
import { Component } from '@angular/core';
import {
    DatePipe,
    CurrencyPipe,
    UpperCasePipe,
    DecimalPipe,
    PercentPipe,
    TitleCasePipe,
    SlicePipe
} from '@angular/common';

@Component({
    selector: 'app-pipes-demo',
    standalone: true,
    imports: [DatePipe, CurrencyPipe, UpperCasePipe, DecimalPipe, PercentPipe, TitleCasePipe, SlicePipe],
    template: `
        <p>Today: {{ today | date:'fullDate' }}</p>
        <p>Short date: {{ today | date:'dd/MM/yyyy' }}</p>
        <p>Name: {{ name | uppercase }}</p>
        <p>Title: {{ title | titlecase }}</p>
        <p>Price: {{ price | currency:'USD':'symbol':'1.2-2' }}</p>
        <p>Pi: {{ pi | number:'1.3-5' }}</p>
        <p>Ratio: {{ ratio | percent:'1.0-1' }}</p>
        <p>{{ name | uppercase | slice:0:5 }}</p>
    `
})
export class PipesDemoComponent {
    today = new Date();
    name = 'tutorials logic';
    title = 'angular pipes introduction';
    price = 1234.5;
    pi = 3.14159265;
    ratio = 0.825;
}

This example shows why pipes are convenient. The raw values stay simple in the component, while the template decides how those values should appear to the user.

Frequently Used Built-in Pipes

DatePipe is one of the most commonly used pipes because applications often need to display dates in user-friendly formats. You can show a full date, short date, month name, time, or a custom pattern. This is useful in dashboards, reports, blog posts, booking systems, and admin panels.

CurrencyPipe, DecimalPipe, and PercentPipe are common in e-commerce, finance, analytics, and reporting. They help make numbers readable without adding formatting logic directly in the component class.

JsonPipe is especially useful while debugging. It should not usually be treated as a final production display tool for users, but it is excellent for inspecting objects during development.

AsyncPipe

The AsyncPipe deserves special attention because it behaves differently from display-only pipes. It subscribes to an Observable or Promise, returns the latest emitted value, and automatically handles cleanup when the view is destroyed. This makes it extremely useful in Angular applications that rely on RxJS or asynchronous data sources.

AsyncPipe Example
import { Component } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { interval, map } from 'rxjs';

@Component({
    selector: 'app-clock',
    standalone: true,
    imports: [AsyncPipe],
    template: `
        <p>Seconds passed: {{ seconds$ | async }}</p>
    `
})
export class ClockComponent {
    seconds$ = interval(1000).pipe(
        map(value => value + 1)
    );
}

Without AsyncPipe, developers often subscribe manually in the component and then remember to clean up later. The async pipe reduces that boilerplate and keeps the template expressive.

KeyValuePipe

The KeyValuePipe is useful when you need to iterate over object properties in a template. Since templates are often designed around arrays, this pipe helps convert object data into an iterable form.

KeyValuePipe Example
import { Component } from '@angular/core';
import { KeyValuePipe } from '@angular/common';

@Component({
    selector: 'app-settings-view',
    standalone: true,
    imports: [KeyValuePipe],
    template: `
        @for (item of settings | keyvalue; track item.key) {
            <p>{{ item.key }}: {{ item.value }}</p>
        }
    `
})
export class SettingsViewComponent {
    settings = {
        theme: 'dark',
        language: 'English',
        notifications: true
    };
}

Creating a Custom Pipe

When the built-in pipes do not solve your formatting need, you can create a custom pipe. A custom pipe is declared using the @Pipe() decorator and must implement the PipeTransform interface. The main logic goes inside the transform() method.

Custom Pipe - Truncate Text
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'truncate',
    standalone: true
})
export class TruncatePipe implements PipeTransform {
    transform(value: string, limit = 50, ellipsis = '...'): string {
        if (!value) return '';
        if (value.length <= limit) return value;
        return value.substring(0, limit) + ellipsis;
    }
}
import { Component } from '@angular/core';
import { TruncatePipe } from './truncate.pipe';

@Component({
    selector: 'app-article',
    standalone: true,
    imports: [TruncatePipe],
    template: `
        <p>{{ longText | truncate }}</p>
        <p>{{ longText | truncate:20 }}</p>
        <p>{{ longText | truncate:30:' [read more]' }}</p>
    `
})
export class ArticleComponent {
    longText = 'Angular is a powerful framework for building modern web applications with TypeScript.';
}

Custom pipes are a good fit for small reusable view transformations such as truncating text, formatting labels, displaying initials, or converting status codes into readable output. If the logic becomes heavy or has side effects, it is usually better placed in a service or component method.

Pure vs Impure Pipes

By default, Angular pipes are pure. A pure pipe runs only when Angular detects that the input reference has changed. This makes pure pipes efficient and suitable for most formatting needs. An impure pipe, on the other hand, runs on every change detection cycle. That makes impure pipes more flexible, but also more expensive.

TypeRuns whenPerformanceTypical use
Pure (default)Input reference changesFastFormatting values for display
Impure (pure: false)Every change detection cycleSlowerRare special cases with mutable inputs

Beginners often hear about impure pipes in the context of filtering arrays, but this needs care. In modern Angular, filtering in the template with an impure pipe is usually not the best default choice for performance-sensitive applications.

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

@Pipe({
    name: 'filter',
    standalone: true,
    pure: false
})
export class FilterPipe implements PipeTransform {
    transform(items: any[], searchText: string, field: string): any[] {
        if (!items || !searchText) return items;
        return items.filter(item =>
            item[field]?.toLowerCase().includes(searchText.toLowerCase())
        );
    }
}

This works, but because the pipe runs frequently, it can become expensive in larger lists. It is usually better to compute filtered results in the component or with signals so Angular recalculates only when needed.

Pipes with Signals in Modern Angular

In modern Angular, especially with signals, many transformations that might once have been written as impure pipes are now better expressed using computed(). Computed signals only recalculate when their dependencies change, which is more efficient and often easier to reason about.

computed() Instead of Impure Pipe
import { Component, signal, computed } from '@angular/core';

interface User { id: number; name: string; role: string; }

@Component({
    selector: 'app-user-list',
    standalone: true,
    template: `
        <input (input)="search.set($any($event.target).value)" placeholder="Search users..." />
        <p>Showing {{ filtered().length }} of {{ users().length }} users</p>
        @for (user of filtered(); track user.id) {
            <div>{{ user.name }} - {{ user.role }}</div>
        }
    `
})
export class UserListComponent {
    search = signal('');

    users = signal<User[]>([
        { id: 1, name: 'Alice', role: 'Admin' },
        { id: 2, name: 'Bob', role: 'Developer' },
        { id: 3, name: 'Charlie', role: 'Designer' },
    ]);

    filtered = computed(() =>
        this.users().filter(u =>
            u.name.toLowerCase().includes(this.search().toLowerCase())
        )
    );
}

This pattern is often a better fit than an impure filtering pipe because the logic stays explicit and recomputation happens only when the dependent signals actually change.

When to Use a Pipe and When Not To

Use a pipe when the logic is mainly about display formatting. For example, converting text to title case, truncating text, showing a date, formatting a price, or presenting a JSON object for debugging are all good pipe use cases.

Avoid putting heavy business logic, network calls, or mutation-driven behavior inside pipes. A pipe should not become a hidden service or a complicated data-processing layer. If the logic needs external dependencies, has side effects, or is central to application behavior rather than presentation, it usually belongs in the component, a service, or a computed signal instead.

Common Beginner Mistakes

  • Using a pipe for heavy logic that should really live in a component or service.
  • Assuming AsyncPipe is only a formatter when it actually manages subscriptions too.
  • Overusing impure pipes for filtering or sorting large data sets.
  • Forgetting to import standalone pipes when using them in standalone components.
  • Expecting a pipe to permanently change the original value instead of only changing the displayed result.

Summary

Pipes are one of Angular's cleanest features for template-level transformations. They make values easier to display, keep templates expressive, and reduce formatting clutter in components. Built-in pipes handle many common needs immediately, while custom pipes let you create reusable view transformations for your own application. Once you understand when to use pure pipes, when to avoid impure ones, and when a computed signal or service is a better fit, pipes become a very practical part of Angular development.

Key Takeaways
  • Pipes transform values for display inside Angular templates using the | operator.
  • Built-in pipes such as date, currency, uppercase, json, and async cover many common use cases.
  • Custom pipes are created with @Pipe() and a transform() method.
  • Pure pipes are fast and run when input references change; impure pipes run much more often and should be used carefully.
  • AsyncPipe is especially important because it subscribes to asynchronous values and handles cleanup automatically.
  • In modern Angular, some transformations are better handled with computed() signals than with impure pipes.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.