We use cookies to enhance your experience on the site
CodeWorlds

Custom Pipes

Pipes transform data in templates - like a master craftsman polishing a sword blade.

Simple Pipe

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 with Dependency Injection

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}

Async Pipe Alternative

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>

Filter Pipe

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>
Go to CodeWorlds