Pipes sind ein leistungsstarkes Konzept in Angular, das die Transformation von Daten direkt in Templates ermöglicht. Angular bietet zahlreiche integrierte Pipes und erlaubt die Erstellung eigener, kundenspezifischer Pipes für flexible Datentransformationen.
Pipes nehmen Eingabedaten entgegen, transformieren sie und geben das Ergebnis zurück. Die Syntax ist einfach und leicht verständlich:
{{ daten | pipeName:parameter1:parameter2 }}Diese Pipes wandeln Text in Groß- bzw. Kleinbuchstaben um:
<p>{{ "Hallo Welt" | uppercase }}</p> <!-- Ergebnis: HALLO WELT -->
<p>{{ "Hallo Welt" | lowercase }}</p> <!-- Ergebnis: hallo welt -->Formatiert jeden Wortanfang mit einem Großbuchstaben:
<p>{{ "willkommen bei angular" | titlecase }}</p> <!-- Ergebnis: Willkommen Bei Angular -->Formatiert Zahlen mit spezifizierten Dezimalstellen:
<p>{{ 3.14159265 | number:'1.2-4' }}</p> <!-- Ergebnis: 3,1416 (je nach Locale) -->Die Parameter geben an: - 1: Mindestanzahl von
Ganzzahlstellen - 2: Mindestanzahl von Dezimalstellen -
4: Maximalanzahl von Dezimalstellen
Die CurrencyPipe bietet Optionen für internationale Währungsformatierung:
<p>{{ 49.99 | currency:'EUR':'symbol':'1.2-2':'de' }}</p> <!-- Ergebnis: 49,99 € -->
<p>{{ 49.99 | currency:'USD':'code':'1.2-2' }}</p> <!-- Ergebnis: USD 49.99 --><p>{{ 0.8457 | percent:'1.1-2' }}</p> <!-- Ergebnis: 84,6% (je nach Locale) -->Die DatePipe bietet verschiedene Formatierungsoptionen und Unterstützung für verschiedene Zeitzonen:
<p>{{ heute | date:'full':undefined:'de' }}</p> <!-- Vollständiges Datum auf Deutsch -->
<p>{{ heute | date:'dd.MM.yyyy HH:mm' }}</p> <!-- Benutzerdefiniertes Format: 20.03.2025 14:30 -->
<p>{{ heute | date:'medium':'GMT+2' }}</p> <!-- Mit Zeitzonenangabe -->Die DatePipe unterstützt ISO 8601 Formate und bietet eine API für Zeitzonen.
Schneidet Arrays oder Strings basierend auf Start- und Endindex:
<p>{{ [1, 2, 3, 4, 5] | slice:1:4 }}</p> <!-- Ergebnis: [2, 3, 4] -->
<p>{{ "Angular" | slice:0:5 }}</p> <!-- Ergebnis: Angul -->Transformiert ein Objekt oder eine Map in ein Array von key-value Paaren:
<div *ngFor="let item of {name: 'Max', alter: 30} | keyvalue">
{{item.key}}: {{item.value}}
</div>Konvertiert ein Objekt in einen JSON-String:
<pre>{{ komplexesObjekt | json }}</pre>Die AsyncPipe abonniert automatisch ein Observable oder Promise und gibt dessen letzten Wert zurück:
<div *ngIf="datenObservable | async as daten">
{{ daten.name }}
</div>Sie kümmert sich auch um das Abmelden beim Zerstören der Komponente.
Eine der Stärken von Angular Pipes ist die Möglichkeit, mehrere Pipes zu verketten:
<p>{{ datum | date:'fullDate' | uppercase }}</p>Die meisten Pipes akzeptieren Parameter, die durch Doppelpunkte getrennt werden:
{{ wert | pipe:param1:param2 }}Um eine eigene Pipe zu erstellen, implementieren Sie das
PipeTransform-Interface:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'shorten',
standalone: true // Für neuere Angular-Versionen
})
export class ShortenPipe implements PipeTransform {
transform(value: string, maxLength: number = 50): string {
if (!value) return '';
if (value.length <= maxLength) {
return value;
}
return value.substring(0, maxLength) + '...';
}
}Verwendung im Template:
<p>{{ langerText | shorten:25 }}</p>@Pipe({
name: 'filterByCategory',
pure: true // Standard, kann weggelassen werden
})Pure Pipes werden nur ausgeführt, wenn: - Der Eingabewert sich ändert (durch Referenzvergleich) - Die Parameter sich ändern
@Pipe({
name: 'filterItems',
pure: false
})
export class FilterItemsPipe implements PipeTransform {
transform(items: any[], searchTerm: string): any[] {
if (!items || !searchTerm) {
return items;
}
return items.filter(item =>
item.name.toLowerCase().includes(searchTerm.toLowerCase())
);
}
}Impure Pipes werden bei jedem Change Detection-Zyklus ausgeführt, was sie für Array- oder Objektfilterung nützlich, aber potenziell leistungsintensiv macht.
Moderne Angular-Versionen unterstützen verbesserte Dependency Injection:
import { Pipe, PipeTransform, inject } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { map, Observable, startWith, switchMap } from 'rxjs';
@Pipe({
name: 'smartTranslate',
standalone: true
})
export class SmartTranslatePipe implements PipeTransform {
private translateService = inject(TranslateService);
transform(key: string, dynamicParams?: Observable<any>): Observable<string> {
if (!dynamicParams) {
return this.translateService.get(key);
}
return dynamicParams.pipe(
switchMap(params => this.translateService.get(key, params)),
startWith('') // Gibt einen Startwert zurück, während auf die Übersetzung gewartet wird
);
}
}Diese Pipe nutzt Dependency Injection mit inject() und
gibt ein Observable zurück, das mit AsyncPipe verwendet werden kann.
Neuere Angular-Versionen unterstützen Signale in Pipes:
import { Pipe, PipeTransform, Signal, computed } from '@angular/core';
@Pipe({
name: 'signalTransform',
standalone: true
})
export class SignalTransformPipe implements PipeTransform {
transform<T, R>(signal: Signal<T>, fn: (value: T) => R): Signal<R> {
return computed(() => fn(signal()));
}
}Verwendung:
<p>{{ countSignal | signalTransform: value => value * 2 }}</p>Verwenden Sie Pure Pipes wann immer möglich Pure Pipes sind wesentlich effizienter, da sie nur bei tatsächlichen Wertänderungen ausgeführt werden.
Vermeiden Sie komplexe Logik in Templates Nutzen Sie Pipes, um komplexe Transformationen aus den Templates zu extrahieren.
TypeScript-Typsicherheit nutzen Angular bietet verbesserte Typsicherheit für Pipes:
transform(value: string[], searchTerm: string): string[] {
// Typsichere Implementierung
}Standalone Pipes bevorzugen In neueren Angular-Versionen sind Standalone-Komponenten der bevorzugte Weg:
@Pipe({
name: 'example',
standalone: true
})Pipes testen Ein einfacher Test für eine Pipe:
describe('ShortenPipe', () => {
let pipe: ShortenPipe;
beforeEach(() => {
pipe = new ShortenPipe();
});
it('should shorten text longer than maxLength', () => {
expect(pipe.transform('This is a long text', 10)).toBe('This is a ...');
});
it('should not modify text shorter than maxLength', () => {
expect(pipe.transform('Short', 10)).toBe('Short');
});
});import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter',
standalone: true
})
export class SearchFilterPipe implements PipeTransform {
transform<T>(items: T[], searchText: string, property?: keyof T): T[] {
if (!items || !searchText) {
return items;
}
searchText = searchText.toLowerCase();
return items.filter(item => {
if (property) {
const value = String(item[property]).toLowerCase();
return value.includes(searchText);
} else {
// Suche in allen String-Properties
return Object.values(item).some(
val => typeof val === 'string' && val.toLowerCase().includes(searchText)
);
}
});
}
}Verwendung:
<input [(ngModel)]="searchTerm" placeholder="Suche...">
<ul>
<li *ngFor="let user of users | searchFilter:searchTerm:'name'">
{{ user.name }} ({{ user.email }})
</li>
</ul>Pipes in Angular sind ein leistungsstarkes Werkzeug zur Datentransformation. Mit Funktionen wie der Integration von Signals, verbesserten Standalone-Komponenten und optimierter Leistung sind sie vielseitig einsetzbar. Durch die Kombination vorhandener Pipes und das Erstellen eigener, anwendungsspezifischer Pipes können Entwickler die Datenpräsentation erheblich verbessern und die Lesbarkeit ihrer Templates steigern.