Angular Pipes: Format Dates, Currency and Text

Angular Tutorial: Beginner to Advanced · 6. Reusable components · 4 min read · Updated

A pipe formats a value

  1. A pipe changes how a value is shown, without changing the value itself.
  2. Put the raw value in the template and add a pipe after the bar sign.
  3. The date pipe turns a timestamp into readable text in the format you choose.
  4. The currency pipe adds the symbol and decimals. Uppercase and lowercase pipes change text.
  5. Pipes can take options and can be chained one after another.

Data in your classes is usually in a raw form: a date as a timestamp, a price as a number, a name in any case. A pipe transforms a value for display, right in the template, with a vertical bar.

What you will learn

  • How to use the common built-in pipes
  • How to pass options to a pipe
  • How to write and use a custom pipe

Built-in pipes

Pipes live in @angular/common. Import the ones a component uses into its imports list:

// src/app/pipes-demo/pipes-demo.ts
import {
  CurrencyPipe,
  DatePipe,
  DecimalPipe,
  JsonPipe,
  PercentPipe,
  SlicePipe,
  TitleCasePipe,
  UpperCasePipe,
} from '@angular/common';
import { Component } from '@angular/core';
import { TruncatePipe } from '../truncate-pipe';

@Component({
  selector: 'app-pipes-demo',
  imports: [CurrencyPipe, DatePipe, DecimalPipe, JsonPipe, PercentPipe, SlicePipe, TitleCasePipe, UpperCasePipe, TruncatePipe],
  template: `
    <ul>
      <li>Date: {{ published | date: 'longDate' }}</li>
      <li>Short date: {{ published | date: 'dd/MM/yyyy' }}</li>
      <li>Price: {{ price | currency }}</li>
      <li>Price in euros: {{ price | currency: 'EUR' }}</li>
      <li>Number: {{ pi | number: '1.0-2' }}</li>
      <li>Percent: {{ ratio | percent }}</li>
      <li>Upper case: {{ name | uppercase }}</li>
      <li>Title case: {{ sentence | titlecase }}</li>
      <li>First three letters: {{ name | slice: 0 : 3 }}</li>
      <li>Object as JSON: <code>{{ user | json }}</code></li>
      <li>Custom pipe: {{ longText | truncate: 30 }}</li>
    </ul>
  `,
})
export class PipesDemo {
  protected readonly published = new Date(2026, 9, 10);
  protected readonly price = 1234.5;
  protected readonly pi = 3.14159;
  protected readonly ratio = 0.256;
  protected readonly name = 'angular';
  protected readonly sentence = 'learning angular is fun';
  protected readonly user = { name: 'Alex', roles: ['student'] };
  protected readonly longText = 'Angular pipes keep your templates clean and readable.';
}

A few things to notice:

  • A pipe follows the value with |, and options follow a colon: date: 'longDate'.
  • Several options are separated by colons, as in slice: 0 : 3.
  • The number pipe uses a format minInt.minFraction-maxFraction. '1.0-2' means at least one digit before the point, and up to two after.
  • The json pipe is handy while debugging because it prints any object as text.
  • Pipes can be chained: {{ name | slice: 0 : 3 | uppercase }}.

Pipes do not change the original value. They only change how it is displayed.

Locale

Dates, numbers and currencies follow a locale, which is en-US by default. Changing it takes a small setup with LOCALE_ID, which the official guide on internationalisation describes. For this course, the default is fine.

Write a custom pipe

When none of the built-in pipes does what you need, write your own. Generate one with ng generate pipe truncate, then edit it:

// src/app/truncate-pipe.ts
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncate',
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit = 40): string {
    if (value.length <= limit) {
      return value;
    }
    return value.slice(0, limit).trimEnd() + '…';
  }
}

The name is how you use it in a template. The transform method receives the value on the left of the bar, followed by any options. Using it is the same as a built-in pipe: add TruncatePipe to imports and write {{ longText | truncate: 30 }}, as the demo does.

Keep pipes pure: they should return the same output for the same input and avoid side effects, such as changing data or calling a server. Angular then only runs them when their inputs change, which keeps pages fast.

// src/app/app.ts
import { Component } from '@angular/core';
import { PipesDemo } from './pipes-demo/pipes-demo';

@Component({
  imports: [PipesDemo],
  selector: 'app-root',
  templateUrl: './app.html',
  styleUrl: './app.css',
})
export class App {}
<!-- src/app/app.html -->
<main>
  <h1>Pipes</h1>
  <app-pipes-demo />
</main>

Try it yourself

  1. Show today's date with new Date() and the format 'fullDate'.
  2. Write a pipe initials that turns "Ada Lovelace" into "AL".
  3. Chain uppercase and slice to show the first four letters of a name in capitals.

Quick check

  1. Which character applies a pipe to a value?
  2. What does a pipe change: the data or how it is displayed?
  3. Where do you list a pipe so that a template can use it?

Next, continue with Angular Built-in Pipes: Date, Async, KeyValue and Using Pipes in Code.

Frequently asked questions

Can a pipe call a server?

A pipe should stay simple and pure. Fetch data in a service and pass the result to the template. The async pipe is a special built-in that reads values from observables.

Is a pipe better than a method in a template?

For formatting, usually yes. A pure pipe only runs again when its input changes, while a method call in a template runs on every check.