Angular 2 Pipes

Angular 2: Pipes

Writing Angular using TypeScript brings a few very nice features for a developer. For instance, you can define Enum, which in my case is defining which source portal the video is coming from (YouTube, Vimeo, Channel9). So when you add a video, this property is automatically suggested based on the URL. I have first created a <select> element in my video form, in order to let user provide this value by himself. So now you have Enum, and need to fill options within select element based on enum values. The situation is quite convenient, because enum types assumes integer value based on string key, so very similar to the HTML <select> tag. But how does one do this in Angular 2?

Pipes to the rescue

Pipes is a concept that allows chaining values transformation, as the documentation says:

Welcome, Angular pipes, the simple display-value transformations that we can declare in our HTML!

A pipe takes in data as input and transforms it to a desired output

An example may be a value that is supposed to represent currency amount. You’d want to keep an integer in your model and want to display it the view in some specific format – like displaying $ before, or after, showing 2 or 4 decimal numbers, etc. That’s a perfect case for Angular 2 pipes application, in this particular case, a CurrencyPipe built-in pipe.

The pipes are applied to a given value using the pipe operator (|). I will show some more examples below.

Built-in Pipes

Angular 2 comes with a set of pipes that are ready to use by the developers, to help making the output clean and nice. I will show few examples and let you refer to the documentation for the other ones.

Starting from some easy example, Upper/Lower case pipes are quite obvious in what is the expected result. Accepted input is transformed so that all letters on output are in either upper, or lower case, depending on which one is used. So if we use interpolation like that:

{{"abc" | uppercase}}

The result will be “ABC”. Of course lowercase transforms the letters the other way around.

I18n stands for Internationalization, which is used to describe the process of making the application usable with many languages. Angular 2 comes with two built-in pipes that are helping with this process. The easy case is described in documentation, so I will not cover it much here in details, but if you want to get a nice example of how you could use it, you should check the angular2localization library on npm.

This one is an interesting example of Pipes application. It allows you to subscribe to an observable and get you updated when the next values are populated. So you could do something like that:

*ngFor="#obj of observableObject| async"

This will cause the UI to update when new values arrive. Very nice.

I will let you refer to the docs for those pipes description, for some of them the behavior could be easily concluded from the name . The pipes are rather a simple thing to understand, so it should be enough to start with.

Last, but not least, if you want to import the standard pipes into your component, you can use the ‘COMMON_PIPES’

import { COMMON_PIPES } from '@angular/common';

COMMON_PIPES is just a const that Angular 2 provides as a shorthand to all the built-in pipes, so that you don’t need to import them separately.

You can check it on github, which will also give you a reference to the list of all pipes implemented by Angular team.

Custom Pipes

The standard pipes come handy, but there’s not too many of them, plus  they are rather a simple ones, as it usually happens with standard implementations. What if we want to go beyond this standard functionality?

SELECT tag to TypeScript Enum binding in Angular 2

I have already mentioned that for my website I needed to fill <select> options with values depending on the enumeration type, they kind of match in terms of representation (Key/Value) but it doesn’t seem obvious how you can bind them together. Let’s stick to this example.

Pipe is generally speaking a class, implementing a specific interface ‘PipeTransform’ coming from standard library, which contains only one method: transform.

export interface PipeTransform {
 transform(value: any, ...args: any[]): any;
}

You need to decorate your class with @Pipe decorator from angular, providing the name of your pipe. Of course, before you begin, you have to import things from the standard library. The implementation of pipe I needed for my enum transformation you can find below.

import {Pipe, PipeTransform} from 'angular2/core';


@Pipe({name: 'keys'})
export class EnumKeysPipe implements PipeTransform {
 transform(value, args:string[]) : any {
 let keys = [];
 for (var enumMember in value) {
 var isValueProperty = parseInt(enumMember, 10) &amp;amp;gt;= 0
 if (isValueProperty) {
 keys.push({key: enumMember, value: value[enumMember]}); 
 } 
 }
 return keys;
 }
}

The implementation of transform method in this case is more complex due to the enums conversion than the Pipes itself. The transform method receives the value to transform (in our case enum type variable), with optional list  of additional arguments (empty in our case) and returns an array of simple objects composed from key and value.

If you want to use such pipe in your code, you first have to import it and register in your component:


import {EnumKeysPipe} from '...';
import {VideoOriginEnum} from '...';

@Component(
 {
...
 pipes: [EnumKeysPipe]
...})

 

You need to declare in your component a variable that will be used to iterate over the enum values (videoOrigins in my case).

videoOrigins = VideoOriginEnum;

The application of such pipe is then as easy as:

<select class="form-control" [(ngModel)]="videoDetails.videoOrigin">
 <option *ngFor="#origin of videoOrigins | keys" [value]="origin.key">
   {{origin.value}}
  </option>
</select>

The expected result in HTML is:

<select class="form-control ng-pristine ng-valid ng-touched">
 <!--template bindings={}-->
  <option value="0">Unknown</option>
  <option value="1">YouTube</option>
  <option value="2">Vimeo</option>
  <option value="3">Channel9</option>
</select>

And that’s it. I think it’s a really nice object-oriented way of doing stuff and it doesn’t take much time to implement while the results are very nice.

Finally, I have decided that I will set this VideoOrigin on the base of url parsing, so I removed it from my component. In any case, I learned this new stuff and hopefully so did you after reading this post. Stay tuned.

Leave a Reply

Your email address will not be published. Required fields are marked *