close icon
Angular

Angular 2 Series - Part 1: Working with Pipes

Learn how to implement pipes (formerly known as filters) in your Angular 2 apps

September 03, 2015


TL;DR: In this first installment of the Angular 2 series, we take a look at pipes which replace filters from Angular 1.x. Many of the filters from Angular 1.x carry over to pipes, but we also get some new ones. Check out the repo for this tutorial to see the pipes in action and to learn how to create your own custom pipes. To see an example of a full Angular 2 app, read Auth0's tutorial on creating your first Angular 2 app.


Auth0's Angular 2 series brings you tutorials on how to implement the latest features from the framework using the most recent Alpha release at the time of writing.

From Filters to Pipes

AngularJS 1.x filters are helpful for formatting output in our templates. With Angular 2, we get this same great feature, but they are now called pipes. At the time of this writing, Angular 1.x and Angular 2 have an equal number of filters to pipes, but there isn't direct crossover. The following table shows a comparison:

Filter/Pipe Name Angular 1.x Angular 2
currency
date
uppercase
json
limitTo
lowercase
number
orderBy
filter
async
decimal
percent

In this article, we will explore the features provided by some of Angular 2's pipes that aren't comparable to Angular 1.x filters. We'll also learn how to create a custom pipe and use it in our templates.

You'll need to have an Angular 2 sandbox set up for this tutorial. A good one to get started with is ng2-play by Pawel Kozlowski.

Basic Pipes

Many of the pipes provided by Angular 2 will be familiar if you've worked with filters in Angular 1.x. Pipes are accessed in our templates in the same way that filters were--with the "pipe" character |. For example, we can use the date pipe to transform a date object in any way we like by providing it with an argument for formatting:

// app.ts

/// <reference path="typings/angular2/angular2.d.ts" />

import {Component, View, bootstrap} from 'angular2/angular2';

@Component({
  selector: 'pipes'
})
@View({
  templateUrl: 'pipesTemplate.html'
})
// Component controller
class PipesAppComponent {
  date: Date;

  constructor() {
    this.date = new Date();
  }
}

bootstrap(PipesAppComponent);

We pointed our @View decorator to a templateUrl in which we make use of the date pipe:

  <!-- pipesTemplate.html -->
  <h1>Dates</h1>
  <!-- Sep 1, 2015 -->
  <p>{{ "{{date | date:'mediumDate'" }}}}</p>
  <!-- September 1, 2015 -->
  <p>{{ "{{date | date:'yMMMMd'" }}}}</p>
  <!-- 3:50 pm -->
  <p>{{ "{{date | date:'shortTime'" }}}}</p>

angular2

New Pipes

The decimal and percent pipes are new in Angular 2. These take an argument that describes the "digit info" that should be used--that is, how many integer and fraction digits the number should be formatted with. The argument we pass for formatting follows this pattern: {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}.

Note: The decimal pipe is accessed using number in our templates.

// app.ts

...

@View({
  templateUrl: 'pipesTemplate.html'
})

class PipesAppComponent {
  grade: number;
  rating: number;

  constructor() {
    this.grade = 0.99;
    this.rating = 9.1243;
  }
}

...
  <h1>Decimals/Percentages</h1>
  <!-- 99.00% -->
  <p>{{ "{{grade | percent:'.2'" }}}}</p>
  <!-- 09.12 -->
  <p>{{ "{{rating | number:'2.1-2'" }}}}</p>

angular2

The Async Pipe

Angular 2 provides a special pipe known as async, which allows us to bind our templates directly to values that arrive asynchronously. This ability is great for working with promises and observables. To see how this works, we'll create a simple promise and have it resolve with a string.

"Angular 2's async allows us to bind our templates directly to values that arrive asynchronously"

Tweet

Tweet This

// app.ts

...

@Component({
  selector: 'pipes',
  changeDetection: 'ON_PUSH'
})
@View({
  templateUrl: 'pipesTemplate.html',
})

class PipesAppComponent {
  promise: Promise;

  constructor() {
    this.promise = new Promise(function(resolve, reject) {
      setTimeout(function() {
        resolve("Hey, I'm from a promise.");
      }, 2000)
    });
  }
}

...
  <!-- pipesTemplate.html -->
  <h1>Async</h1>
  <p>{{ "{{ promise | async" }}}}</p>

After a 2 second delay, the value from the resolved promise will be displayed on the screen.

angular2

Custom Pipes

Before Alpha 35, we had to configure our custom pipes with a pipes object. However, we can now define a pipe with the decorator @Pipe and use it by adding a pipes property to the @View decorator with the name of the pipe class. This makes it easier and more convenient to register our custom pipes.

// app.ts

import {Component, View, bootstrap, Pipe, PipeTransform} from 'angular2/angular2';

...

// We use the @Pipe decorator to register the name of the pipe
@Pipe({
  name: 'tempConvert'
})
// The work of the pipe is handled in the tranform method with our pipe's class
class TempConvertPipe implements PipeTransform {
  transform(value: number, args: any[]) {
    if(value && !isNaN(value) && args[0] === 'celsius') {
      var temp = (value - 32) * 5/9;
      var places = args[1];
      return temp.toFixed(places) + ' C';       
    }

    return;
  }
}

...

@View({
  templateUrl: 'pipesTemplate.html',

  // We can pass the pipe class name into the pipes key to make it usable in our views
  pipes: [TempConvertPipe]
})

class PipesAppComponent {
  temperature: number;

  constructor() {
    this.temperature = 85;
  }
}
  <h1>Custom Pipes - Convert Temperature</h1>
  <!-- 85 F -->
  <h3>Fahrenheit: {{ "{{temperature + ' F'" }}}}</h3>
  <!-- 29.4 C -->
  <h3>Celsius: {{ "{{temperature | tempConvert:'celsius':1" }}}}</h3>

We use the transform method to do any logic necessary to convert the value that is being passed in. We can get ahold of the arguments array as the second parameter and pass in as many as we like from the template. As you can see here, we check the type of conversion that we want (e.g., Fahrenheit to Celsius), convert the value passed in, and then return the converted value to the number of decimal places specified in the second argument of the pipe.

As mentioned above, we need to provide an array to the pipes property in the @View decorator to use the new pipe.

angular2

Aside: Using Angular with Auth0

Auth0 issues JSON Web Tokens on every login for your users. This means that you can have a solid identity infrastructure, including Single Sign On, User Management, support for Social (Facebook, Github, Twitter, etc.), Enterprise (Active Directory, LDAP, SAML, etc.) and your own database of users with just a few lines of code. We implemented a tight integration with Angular 1. Angular 2 integration is coming as soon as it's on Beta! You can read the documentation here or you can checkout the SDK on Github.

Wrapping Up

Angular 2 provides some great pipes that carry over well from the filters we are used to in Angular 1.x. We also get some new pipes that give us special functionality, such as the async pipe, which binds our templates to asynchronous resources. It's also easy to create our own pipes via the @Pipe decorator and the pipes key in our @View decorators.

You can find the code for this tutorial on GitHub.

  • Twitter icon
  • LinkedIn icon
  • Faceboook icon