Cours Angular · Module 14: Patterns avancés
Les pipes personnalisés
Dans cette leçon4
Les pipes transforment les données dans les templates - comme un maître artisan qui polit la lame d'un sabre.
Pipe simple
1@Pipe({
2 name: 'truncate',
3 standalone: true
4})
5export class TruncatePipe implements PipeTransform {
6 transform(value: string, limit = 50, trail = '...'): string {
7 if (!value) return '';
8 if (value.length <= limit) return value;
9 return value.substring(0, limit) + trail;
10 }
11}
12
13// Usage
14<p>{{ longText | truncate }}</p>
15<p>{{ longText | truncate:100:'...' }}</p>Pipe avec injection de dépendances
1@Pipe({
2 name: 'relativeTime',
3 standalone: true
4})
5export class RelativeTimePipe implements PipeTransform {
6 private locale = inject(LOCALE_ID);
7
8 transform(value: Date | string): string {
9 const date = new Date(value);
10 const now = new Date();
11 const diffMs = now.getTime() - date.getTime();
12 const diffMins = Math.floor(diffMs / 60000);
13 const diffHours = Math.floor(diffMs / 3600000);
14 const diffDays = Math.floor(diffMs / 86400000);
15
16 if (diffMins < 1) return 'just now';
17 if (diffMins < 60) return `${diffMins} min ago`;
18 if (diffHours < 24) return `${diffHours} hours ago`;
19 if (diffDays < 7) return `${diffDays} days ago`;
20
21 return date.toLocaleDateString(this.locale);
22 }
23}Alternative au pipe async
1@Pipe({
2 name: 'safeAsync',
3 standalone: true,
4 pure: false // Impure - checks on every change detection
5})
6export class SafeAsyncPipe implements PipeTransform, OnDestroy {
7 private subscription?: Subscription;
8 private latestValue: any = null;
9
10 transform<T>(obs: Observable<T>, defaultValue: T): T {
11 if (!this.subscription) {
12 this.subscription = obs.subscribe(value => {
13 this.latestValue = value;
14 });
15 }
16 return this.latestValue ?? defaultValue;
17 }
18
19 ngOnDestroy(): void {
20 this.subscription?.unsubscribe();
21 }
22}
23
24// Usage
25<p>{{ data$ | safeAsync:'Loading...' }}</p>Pipe de filtrage
1@Pipe({
2 name: 'filter',
3 standalone: true
4})
5export class FilterPipe implements PipeTransform {
6 transform<T>(items: T[], predicate: (item: T) => boolean): T[] {
7 if (!items || !predicate) return items;
8 return items.filter(predicate);
9 }
10}
11
12// Usage with function
13<div *ngFor="let samurai of samuraiList | filter:isActive">
14 {{ samurai.name }}
15</div>Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Quelle est la différence entre un pipe pur et un pipe impur ?
2. Quelle interface une classe de pipe doit-elle implémenter, et quelle méthode impose-t-elle ?
Tâches pratiques dans le jeu
- Tri horizontal
Ordonne sur une seule ligne l'expression qui appelle le pipe truncate avec une limite de 100 dans un template :
- Éditeur de code
Complète le pipe personnalisé qui tronque un texte à une longueur donnée.
- Clique dans l'ordre
Clique sur les éléments dans l'ordre pour construire le début du décorateur de pipe : @Pipe({
- Tri vertical
Ordonne les lignes de la définition du pipe truncate (de haut en bas) :