Angular pipes : built-in et pipes personnalisés

🏷️ Front-end 📅 12/04/2026 22:00:00 👤 Mezgani said
Angular Pipes Angular 17 Angular 18
Angular pipes : built-in et pipes personnalisés

Maîtrisez les pipes Angular : découvrez les pipes intégrés (date, currency, async) et créez vos propres pipes personnalisés pour transformer vos données.

Qu'est-ce qu'un pipe Angular

Un pipe est une fonction de transformation qui s'utilise directement dans les templates Angular avec l'opérateur |. Il prend une valeur en entrée, l'applique, et retourne une valeur transformée.

<!-- Sans pipe -->
<p>{{ getPrix(product.price) }}</p>

<!-- Avec pipe -->
<p>{{ product.price | currency:'EUR':'symbol':'1.2-2':'fr' }}</p>

Les pipes sont purs par défaut : Angular ne les réexécute que si la valeur d'entrée change (référence), ce qui les rend très performants.

Pipes intégrés essentiels

<!-- DatePipe -->
{{ today | date:'dd/MM/yyyy' }}
{{ today | date:'long':'':'fr' }}

<!-- CurrencyPipe -->
{{ price | currency:'EUR':'symbol':'1.2-2':'fr' }}
<!-- Résultat : 1 234,56 € -->

<!-- DecimalPipe -->
{{ 3.14159 | number:'1.2-3' }}
<!-- Résultat : 3,142 -->

<!-- PercentPipe -->
{{ 0.75 | percent }}
<!-- Résultat : 75% -->

<!-- UpperCase / LowerCase / TitleCase -->
{{ 'hello world' | titlecase }}
<!-- Résultat : Hello World -->

<!-- SlicePipe -->
{{ [1, 2, 3, 4, 5] | slice:1:3 }}
<!-- Résultat : [2, 3] -->

<!-- JsonPipe (debug) -->
<pre>{{ data | json }}</pre>

<!-- KeyValuePipe -->
@for (item of obj | keyvalue; track item.key) {
  <p>{{ item.key }}: {{ item.value }}</p>
}

Le pipe async

Le pipe async est particulièrement puissant : il s'abonne automatiquement à un Observable ou une Promise, affiche la valeur émise, et désabonne automatiquement à la destruction du composant.

@Component({
  selector: 'app-users',
  standalone: true,
  imports: [AsyncPipe, NgFor],
  template: `
    @if (users$ | async; as users) {
      @for (user of users; track user.id) {
        <div>{{ user.name }}</div>
      }
    } @else {
      <p>Chargement...</p>
    }
  `
})
export class UsersComponent {
  users$ = this.userService.getAll(); // Observable<User[]>

  constructor(private userService: UserService) {}
}
A retenir : Le pipe async évite les fuites mémoire (memory leaks) car il gère le cycle de vie de la subscription automatiquement. Préférez-le à subscribe() dans le template.

Créer un pipe personnalisé

Générer un pipe avec Angular CLI :

ng generate pipe shared/truncate

Exemple de pipe pour tronquer un texte :

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

@Pipe({
  name: 'truncate',
  standalone: true,
  pure: true  // défaut : true
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, maxLength: number = 100, suffix: string = '...'): string {
    if (!value || value.length <= maxLength) {
      return value;
    }
    return value.substring(0, maxLength).trim() + suffix;
  }
}

Utilisation dans un template :

<!-- Import dans le composant -->
@Component({
  imports: [TruncatePipe],
  template: `
    <p>{{ article.description | truncate:150 }}</p>
    <p>{{ article.content | truncate:80:'… Lire la suite' }}</p>
  `
})

Pipes purs vs impurs

Un pipe pur (défaut) n'est réexécuté que si la référence de la valeur d'entrée change. Un pipe impur s'exécute à chaque cycle de détection de changements.

// Pipe impur : s'exécute à chaque tick (attention aux performances)
@Pipe({
  name: 'filterActive',
  standalone: true,
  pure: false  // impur
})
export class FilterActivePipe implements PipeTransform {
  transform(items: Item[]): Item[] {
    return items.filter(item => item.active);
  }
}

// Alternative recommandée : pipe pur avec objet immuable
// Plutôt que de muter le tableau, créer un nouveau tableau
items = [...this.items, newItem]; // Angular détecte le changement
Note : Évitez les pipes impurs autant que possible. Préférez rendre vos données immuables (spread, map, filter) pour que les pipes purs détectent les changements correctement.

Pipes standalone

Depuis Angular 17, les pipes standalone sont la norme. Un pipe standalone peut être importé directement dans un composant sans passer par un NgModule :

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

// Dans le composant
@Component({
  standalone: true,
  imports: [TruncatePipe],  // importé directement
  template: `{{ text | truncate:100 }}`
})
export class ArticleComponent {}

Vous pouvez également créer une librairie de pipes réutilisables en les exportant depuis un barrel :

// shared/pipes/index.ts
export { TruncatePipe } from './truncate.pipe';
export { FormatFileSizePipe } from './format-file-size.pipe';
export { TimeAgoPipe } from './time-ago.pipe';