Pipe Tricks with AngularDart

Pipes in Angular (known as filters in Angular 1.x) are a nice, convenient way to keep your application data clean, unsullied by visual artifacts, but still present that data to your users in an attractive way. Currency would be a good example of this situation: Users like to see currency symbols, such as dollar signs, with their numbers, but internally, your code has no use for those. You're trying to do math on these numbers. Users also don't care to see currency values with more than two decimal places. With pipes, you can make everyone happy.

Code tested with Dart SDK 1.24.2 and AngularDart 4.0.0.

Dart

Dart is an open-source, scalable, object-oriented programming language, with robust libraries and runtimes, for building web, server, and mobile apps. It was originally developed by Google, but has since become an ECMA standard.

Dart Primers

Check out the Dart Language Tour for a crash course in the Dart language. If you already know JavaScript, Java, PHP, ActionScript, C/C++/C#, or another "curly brace" language, you'll find Dart to be familiar, and you can be productive with Dart within an hour or so.

If you like learning from videos, take a look at Learn Dart in One Video.

Get Dart

Before you can get into the exciting world of writing Dart code, you need to download the Dart SDK and, for web apps, a special browser called Dartium:

AngularDart

AngularDart is the Dart version of the popular Angular web application framework. The concepts and semantics are currently nearly identical, but since AngularDart is a separate project, it is not guaranteed to remain entirely in sync with the TypeScript version. If you're wondering why you might want to use AngularDart instead of the more mainstream Angular, here are 7 reasons.

Quickstart

To get an AngularDart app up and running quickly, try the Quickstart tutorial.

Pipes

A pipe is basically an intermediary transformer that takes in one value, manipulates it in some way, and spits out the new value. Angular provides a number of pipes out of the box, including pipes for formatting dates, making strings uppercase or lowercase, and one for formatting percentage values. You can also create custom pipes.

Making Pipes Available

The typical way to make a pipe available to your Angular component is to import the pipe's class, and then include it in the @Component decorator's pipes list:

lib/app_component.dart

import 'package:angular/angular.dart';

@Component(selector: 'my-app',
    templateUrl: 'app_component.html',
    pipes: const [CurrencyPipe]
)
class AppComponent {

  AppComponent();
}

If it seems laborious to declare commonly used pipes in this way, there is a trick you can use to make all of Angular's pipes available to any given component. Angular has defined a constant called COMMON_PIPES that you can use to get them all in one fell swoop:

lib/app_component.dart

import 'package:angular/angular.dart';

@Component(selector: 'my-app',
    templateUrl: 'app_component.html',
    pipes: const [COMMON_PIPES]
)
class AppComponent {

  AppComponent();
}

With that in place, you'll be able to access all of Angular's handy pipes without declaring them individually.

Percent Pipe

Using one of Angular's built-in pipes, let's take a look at an example. Suppose you have a floating point value representing a percent called progress, and you want to display it in your view:

lib/app_component.dart

class AppComponent {

  num progress = 0.259;

  AppComponent();
}

lib/app_component.html

<p>Total progress is: {{progress}}</p>

The output of Angular's interpolation will be:

Total progress is: 0.259

This output could be confusing to your users, as it supplies no indication that it's a percentage. Let's improve the display with PercentPipe:

lib/app_component.html

<p>Total progress is: {{progress | percent}}</p>

Now the display looks like:

Total progress is: 25.9%

Better! Now it's clear we're talking about a portion of a whole. What if we want more control over the way the number is displayed, though? Maybe it's in a table, and we want all the numbers to line up nicely.

Pipes Can Take Parameters

Luckily, the Angular team hasn't let us down here. Like many pipes, PercentPipe is configurable. It can take one value, digitInfo, which allows you to format the placement of the digits, including using padding when needed:

lib/app_component.html

<p>Total progress is: {{progress | percent:'4.3-5'}}</p>

The argument passed here follows this pattern: {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}

And now you have:

Total progress is: 0025.900%

Async Pipe

Maybe you don't yet have your percentage data. It might be coming from a remote source, delivered to your client asynchronously. This is where the AsyncPipe comes in. Take a look at this example, where we chain the AsyncPipe and PercentPipe to show progress:

lib/app_component.html

<p>Total progress is: {{progressStream | async | percent:'1.2-2'}}</p>

lib/app_component.dart

import 'dart:async';
import 'package:angular/angular.dart';

@Component(selector: 'my-app',
    templateUrl: 'app_component.html'
)
class AppComponent {

  Stream<num> progressStream;

  AppComponent() {
    Duration delay = new Duration(milliseconds: 500);
    progressStream = 
      new Stream.periodic(delay, (int index) => index * 0.005);
  }
}

If you run that code, you'll see the value increasing by 0.5% every half-second as data is fed into progressStream.

Total progress is: 8.50%

Creating Custom Pipes

Of course, you can create your own pipes. A pipe is free to transform a value in any complicated way you want, but in this example, it'll be very simple. It will add the symbol for "degrees" at the end of whatever value is passed in.

First, create the pipe class:

lib/degrees_pipe.dart

import 'package:angular/angular.dart';

@Pipe(name: 'degrees')
class DegreesPipe extends PipeTransform {
  String transform(val, [List args]) => "$val°";
}

Then tell your component about it. For custom pipes, you'll need to remember to add it to the pipes list in your @Component decorator, or your template will not know what you're talking about:

lib/app_component.dart

import 'package:angular/angular.dart';

import 'degrees_pipe.dart';

@Component(selector: 'my-app',
    templateUrl: 'app_component.html',
    pipes: const [DegreesPipe]
)
class AppComponent {

  num temperature = 65;

  AppComponent();
}

And finally, use it in your view template:

lib/app_component.html

<p>Temperature is: {{temperature | degrees}}</p>

And the output:

Temperature is: 65°

Conclusion

Thank you for joining us for this first (and possibly only) edition of Pipe Tricks. Until next time, use Angular, use Dart, and use good judgement.