Angular Tutorial: Working with Angular Pipes

by | Mar 11, 2019

In this blog post we will explore working with Angular’s Pipe API. Angular pipes are used in your templates to transform a data set in some desired way. A prime example of this is the CurrencyPipe which transforms a given number into a currency string. The CurrencyPipe is one of several Angular pipes provided by the Angular framework directly out of the box. In addition to these built-in pipes, developers can create their own custom pipes. Being able to create custom pipes for your project is a useful tool to have in your developer toolbox. 

In this tutorial, we will first explore the basics of using Angular pipes by working with the DatePipe. Then we will create a custom pipe and use it to organize table data. All of this will be done in a PipesExampleModule that I will create inside of the tutorial series project NgExample. If you are not following along and are just interested in information on Angular Pipes, you can skip the next two sections.

 

NgExample

A quick note, this post is a part of a series of Angular posts. All of the code in this post, as well as links to the other posts in this series can be found on GitHub (links to other posts also included below)

Module Setup

In previous examples, we have setup modules for each example. We will continue with that practice here with the following commands. The “core” portion of the reflects how this example repo has been setup. If you aren’t following along from previous examples or your project is setup differently, then “core” can be omitted.

  1. ng g module core/pipes-example
  2. ng g component core/pipes-example

Next, I updated the routing inside the example application as I have previously for other examples. So I will keep those steps brief here.

  1. Import PipesExampleModule into CoreModule
  2. Add a route to PipesExampleComponent in the CoreRoutingModule
  3. Add routing link to the SidebarComponent

Introduction to Angular Pipes and DatePipe Example

As I touched on above, an Angular pipe is used to transform a piece of data. Specifically, a piece of data in a component’s template. Before we get into to much detail, let’s take a look at this in action. Let’s start simple and use the built-in DatePipe to transform a standard Date in our template.

In your component, add the following to create a todaysDate variable that we will bind to the template. (pipes-example.component.ts)

export class PipesExampleComponent implements OnInit {
  todaysDate: Date;
  constructor() {
    this.todaysDate = new Date();
  }
  ngOnInit() {
  }
}

And then update your template with the following. (pipes-example.component.html)

<h6>Today's Date Raw: {{todaysDate}}</h6>
<h6>Today's Date Default: {{todaysDate | date}}</h6>

What we have done in the first line is displayed todaysDate in its standard format. On the second line, we utilized the “date” pipe, “date” being the name of the Angular pipe we wish to use. We’ll discuss more about the name of the pipe when we create a custom pipe below. For now, let’s just take a look at what is displayed in our template when we run ng serve

As we can see, using the date pipe allows us to simply display a user-friendly version of our date. Hopefully, you can appreciate the usefulness of this. Anytime you want to display a date you simply just have to run it through the pipe. Now, the even better part is that we can pass additional arguments to the Angular pipe that will give us more control over how the date is displayed. If you check out the docs for the DatePipe you can see all the options of arguments you can pass to the pipe for how you want the date displayed. Below is an example of how arguments can be passed.

 <h6>Today's Date Short: {{todaysDate | date:'short'}}</h6>
 <h6>Today's Date Medium: {{todaysDate | date:'medium'}}</h6>
 <h6>Today's Date Long: {{todaysDate | date:'long'}}</h6>

Here we are passing a string that matches with one of the pre-determined format options of the DatePipe. The results look like this:

Creating a Custom Pipe

Next, to get a better understanding of how pipes work, we will create our own! We are going to make a pipe that takes in an array of data and sorts it by a given property. Then we will apply the pipe to a table of data. Let’s dive in!

Let’s start by creating our table. We are going to create a table of people with a few different attributes that we can sort against. To do this, create a new file: “people-example-data.ts” in your pipes-example directory and add the following:

export interface Person {
    name: string;
    age: number;
    height: number;
    weight: number;
}

export const People: Array<Person> = [
    { name: 'Allen', age: 26, height: 150, weight: 88 },
    { name: 'Beth', age: 40, height: 144, weight: 70 },
    { name: 'Tara', age: 16, height: 159, weight: 58 },
    { name: 'Zach', age: 31, height: 193, weight: 72 }
]

We’ll use this data to populate our table. In your component, create a variable that holds an array of Person and set it equal to the People data we just created. Your updated component will look like this: (pipes-example.component.ts)

people: Array<Person>;
todaysDate: Date;
constructor() {
   this.todaysDate = new Date();
   this.people = People;
}

Next up we will add the table to our template. The updated template will look like this: (pimpes-example.component.html)

<table>
  <thead>
    <tr>
      <td>Name</td>
      <td>Age</td>
      <td>Height</td>
      <td>Weight</td>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let person of people">
      <td>{{person.name}}</td>
      <td>{{person.age}}</td>
      <td>{{person.height}} cm</td>
      <td>{{person.weight}} kg</td>
    </tr>
  </tbody>
</table>

If you run ng serve now you should see the table of people data in the order that you created it.

Now that we have that out of the way, let’s get to why we are here. We are going to add a pipe onto our people ngFor that will sort it by one of its parameters.

First, we will generate the pipe with the Angular CLI just like any component or module. We will call it “sort-people”

  • ng g pipe core/pipes-example/sort-people

This is going to generate a “SortPeople” pipe in your pipes-example/ directory. Let’s take a look at what has been generated.

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'sortPeople'
})
export class SortPeoplePipe implements PipeTransform {
  transform(value: any, args?: any): any {
    return null;
  }
}

Let’s breakdown what’s packed in here. We are declaring the class as a Pipe using Angular’s syntax. By default, we pass on of the Pipe’s two options. That being the “name” property. This is the pipe’s name to use in the template. Recall “date” is the name of the DatePipe.

Moving on we are declaring that this class implements PipeTransform. To create any pipe you must implement this interface. The transform(value:any, args?: any)function does just that.

As-is, this pipe will take in a value of type any, and additional arguments also of type any. Then it will return null. The returned value is what is used by the template. In the “date” example, the transform function would take in a date string of some kind and return it in the format that was determined by the args. We must fill out our transform()function to return a sorted array of Person’s. To do this I am going to use a library called “lodash”. It can be installed with npm and has utilities for sorting arrays that I will use.

The finished “SortPeople” pipe looks like this: (sort-people.pipe.ts)

import { Pipe, PipeTransform } from '@angular/core';
import { Person } from './pipes-example-data';
import * as _ from 'lodash';
@Pipe({
  name: 'sortPeople'
})
export class SortPeoplePipe implements PipeTransform {
  transform(value: Array<Person>, by: string, direction: "asc" | "desc"): Array<Person> {
    value = _.orderBy(value, [by], direction);
    return value;
  }
}

What I’ve done is defined our “value” as an array of Person’s. Additionally, I defined the two arguments that are needed for sorting, they match the definitions used by lodash. When the pipe is implemented, it will use lodash to order the array given the parameters and then return the sorted value.

Now we just need to apply the pipe to our *ngFor in our template. Our updated template will look like this: (pipes-example.component.ts)

<tbody>
  <tr *ngFor="let person of people | sortPeople:'age':'asc'">
    <td>{{person.name}}</td>
    <td>{{person.age}}</td>
    <td>{{person.height}} cm</td>
    <td>{{person.weight}} kg</td>
   </tr>
</tbody>

Now the “people” will be sorted in ascending order by the “age” property. If you run ng serve you will see the results of your custom sortPeople pipe applied to your table.

Pro-tips

Now that you are familiar with creating your own Angular pipes, you will certainly want to use pipes in your projects. I just want to quickly touch on a few additional tidbits that may be helpful to you.

  • I would suggest creating a CustomPipesModule and placing all of your custom pipes in this module. This will act as a shared module within your project, allowing you to use your custom pipes anywhere necessary.
  • Additionally, component variables can be used as arguments for a pipe. In my ng-example repo, I have created a variable for the component that holds a string corresponding with the column that should be sorted. Then programmatically, clicking the headers, sets the variable and the pipe will update.
  • Pipes can be chained, so you can use more than one pipe on a template binding. Ex: {{ someData | pipe1 | pipe2 }}
    • pipe1 will apply to the data first, followed by pipe2

Summary

With that, you should be able to start using pipes in your Angular projects. We’ve covered how pipes are applied, what the transform() function is within a pipe and how to create a custom pipe. Like I’ve stated a few times, feel free to check out my ng-example repo on github for a working example of this content and links to other entries into this series.