Pipes

Pipes transform values in templates. AngularDart provides built-in pipes and allows you to create custom pipes.

Built-in Pipes

DatePipe

Format dates:

<p>{{ birthday | date }}</p>
<p>{{ birthday | date:'fullDate' }}</p>
<p>{{ birthday | date:'yMMMd' }}</p>
<p>{{ birthday | date:'HH:mm' }}</p>

CurrencyPipe

Format currency values:

<p>{{ price | currency:'USD' }}</p>
<p>{{ price | currency:'EUR' }}</p>
<p>{{ price | currency:'EUR':true }}</p>

NumberPipe

Format numbers:

<p>{{ bigNumber | number }}</p>
<p>{{ pi | number:'1.2-2' }}</p>
<p>{{ percent | percent }}</p>

UpperCasePipe / LowerCasePipe

Transform text case:

<p>{{ name | uppercase }}</p>
<p>{{ title | lowercase }}</p>

JsonPipe

Display objects as JSON (useful for debugging):

<pre>{{ user | json }}</pre>

SlicePipe

Extract a portion of a list or string:

<p>{{ 'Hello World' | slice:0:5 }}</p>
<ul>
  <li *ngFor="let item of items | slice:0:5">{{ item }}</li>
</ul>

AsyncPipe

Unwrap values from streams or futures:

<p>{{ data$ | async }}</p>
<div *ngIf="users$ | async as users">
  <ul>
    <li *ngFor="let user of users">{{ user.name }}</li>
  </ul>
</div>

Chaining Pipes

Combine multiple pipes:

<p>{{ birthday | date:'fullDate' | uppercase }}</p>
<p>{{ price | currency:'EUR' | uppercase }}</p>

Pipes with Parameters

Pass parameters to pipes:

<p>{{ value | number:'1.2-2' }}</p>
<p>{{ date | date:'yMMMd' }}</p>

Creating Custom Pipes

Create custom pipes with the @Pipe annotation:

import 'package:angulardart/angular.dart';

@Pipe('exponentialStrength')
class ExponentialStrengthPipe implements PipeTransform {
  @override
  num transform(num value, num exponent) {
    return value * exponent;
  }
}

Usage:

<p>{{ 2 | exponentialStrength:10 }}</p>

Flying Heroes Pipe

Filter a list with a custom pipe:

@Pipe('flyingHeroes')
class FlyingHeroesPipe implements PipeTransform {
  @override
  List<Hero> transform(List<Hero> heroes) {
    return heroes.where((hero) => hero.canFly).toList();
  }
}

Usage:

<div *ngFor="let hero of heroes | flyingHeroes">
  {{ hero.name }} can fly!
</div>

Custom Date Format Pipe

@Pipe('customDate')
class CustomDatePipe implements PipeTransform {
  @override
  String transform(DateTime date) {
    final now = DateTime.now();
    final diff = now.difference(date);

    if (diff.inMinutes < 1) return 'just now';
    if (diff.inHours < 1) return '${diff.inMinutes} minutes ago';
    if (diff.inDays < 1) return '${diff.inHours} hours ago';
    if (diff.inDays < 7) return '${diff.inDays} days ago';

    return '${date.day}/${date.month}/${date.year}';
  }
}

Usage:

<p>Posted {{ post.date | customDate }}</p>

Search Filter Pipe

@Pipe('searchFilter')
class SearchFilterPipe implements PipeTransform {
  @override
  List<T> transform<T>(List<T> items, String query) {
    if (query.isEmpty) return items;

    return items.where((item) {
      return item.toString().toLowerCase().contains(query.toLowerCase());
    }).toList();
  }
}

Usage:

<input [(ngModel)]="searchQuery" placeholder="Search...">
<ul>
  <li *ngFor="let item of items | searchFilter:searchQuery">
    {{ item }}
  </li>
</ul>

Impure Pipes

By default, pipes are pure (only re-evaluate when input reference changes). Use impure pipes for pipes that need to re-evaluate on every change detection:

@Pipe('fetch', pure: false)
class FetchPipe implements PipeTransform {
  @override
  dynamic transform(Future<dynamic> future) {
    // Return cached value or trigger load
  }
}

Warning: Impure pipes can impact performance. Use them sparingly.

Pipe Best Practices

  • Keep pipes focused on a single transformation
  • Use pure pipes when possible for better performance
  • Name pipes clearly (e.g., shorten, truncate, filter)
  • Consider caching expensive transformations
  • Use pipes for display logic, not business logic

When to Use Pipes vs Components

Use pipes when:

  • Transforming a single value for display
  • The transformation is reusable across templates
  • The logic is simple and stateless

Use components when:

  • The transformation requires complex logic
  • You need to maintain state
  • The transformation involves DOM manipulation