Ionic 2 Pipes

How to Use Pipes to Manipulate Data in Ionic 2



·

Pipes are super useful to have in your application – in general they are used to manipulate data before displaying it to the user (think date conversions, formatting and so on). Before we get into how to use them though, I’ll give a little more background.

You could imagine pipes to be literal pipes that you pass information through, and each pipe does something to the information as it passes through. Let’s say we start off with the strings Robb Stark and Tywin Lannister and we want to convert those strings to only contain the first name, and to have it be all uppercase. To do that we could create two pipes, one that modifies the data to only include the first name and another one that capitalises the remaining string from the result of the previous pipe, which might look something like this:

Pipes in Ionic 2

Of course, we could just do both operations in one pipe, but I wanted to demonstrate how you can pass data through multiple pipes. Pipes have been around for a long time – I’m a little rusty on my pipe history but I imagine the name comes from the use of the pipe ‘|’ character in a command line interface environment.

In a linux environment for example you might have seen commands like this:

grep -ir "findme" | someOtherCommand | oneMoreCommand

This example first searches for some data with grep which matches the findme string. Once it finds that, it will then pass that data through someOtherCommand and then oneMoreCommand. The end result might be a sorted list of entries that contain the findme string.

In Angular and Ionic you might be more used to seeing these pipes in expressions in a template like this:

{{someData | somePipe}}

In Ionic 2 pipes still look like this in the template, but the way in which you create them is a little different. In this tutorial we are going to walk through how to build and use a pipe for filtering data in Ionic 2. If you want to see how to do this in Ionic 1, take a look at this post by Andrew McGivery.

DISCLAIMER: At the time of writing this, Ionic 2 is still in Alpha and things may change. If you find that the code in this tutorial no longer works, let me know and I’ll do my best to update it.

Before we Get Started

Before you go through this tutorial, you should have at least a basic understanding of Ionic 2 concepts. You must also already have Ionic 2 set up on your machine.

If you’re not familiar with Ionic 2 already, I’d recommend reading my Ionic 2 Beginners Guide first to get up and running and understand the basic concepts. If you want a much more detailed guide for learning Ionic 2, then take a look at Building Mobile Apps with Ionic 2.

1. Generate a New Application

Let’s start by generating a new Ionic 2 application by running the following command:

ionic start ionic2-pipes blank --v2

2. Create a Pipe

We’re going to create a new pipe the same way we create just about anything with Ionic 2. We will create a folder for it, define it using a file that contains a class definition and a decorator (decorators are the @Something statements before your class definition), import it into wherever we want to use it, and then use it. Creating a custom pipe is very similar to creating a custom directive.

The pipe we are going to create is one that will replace all words in a string with Matt Damon.

Create a new folder at app/pipes

Create a new file called matt-damon.ts and add the following code:

import {Pipe} from '@angular/core';

@Pipe({
  name: 'mattDamon'
})
export class MattDamon {
  transform(value, args) {
    return value;
  }
}

This is the basic structure of a pipe in Ionic 2, and all it will do right now is return the same value that it was passed. You can see in the transform method we pass in a value and args. The value is the data you are passing through the pipe, and the args are any arguments that have been passed to the pipe (which can be used to alter what the pipe does).

The syntax for using a pipe in a template looks like this:

{{data | pipe}}

so we could use our Matt Damon pipe like this:

{{myString | mattDamon}}

or maybe we would want to create a more generic version of the pipe that could replace all the words in a string with anybody’s name that is supplied to the pipe using args, i.e:

{{myString | mattDamon:"Josh Morony"}}

If you want to get even fancier, you can even pass in multiple arguments to the pipe using an array like this:

{{myString | mattDamon:["Josh Morony", "something"]}}

So our transform method in the pipe will receive our data through the value parameter, and an array of arguments through the args parameter. Whatever value is used in the return statement is what the data will display as in the template, so you can modify the incoming data in any way you want before returning it, or even just return something completely different.

Now that we understand how a pipe works, let’s finish off our Matt Damon pipe by altering the value before we return it.

Modify matt-damon.ts to reflect the following:

import {Pipe} from '@angular/core';

@Pipe({
  name: 'mattDamon'
})
export class MattDamon {
  transform(value, args) {

    //Count how many words were passed in
    let wordCount = value.split(" ").length;
    let newValue = "";

    for(let i = 0; i < wordCount; i++){
        newValue += "Matt Damon ";
    }

    return newValue;
  }
}

Now we’ve added some code that will take the value that is passed in, count how many words are in the string, and then return a string containing the same number of “Matt Damon”‘s. You could do this by using regular expressions to match words instead, but I still haven’t got my head around regex and I think this is way easier to understand anyway.

3. Using a Pipe

Our pipe is ready to be used now, but it’s existence in the project is not enough to use it anywhere. We still need to import it and add it to the decorator of the page we want to use it on.

Let’s use one of the auto generated tabs to practice using our new pipe.

Modify page1.js to reflect the following

import {Component} from '@angular/core';
import {MattDamon} from '../../pipes/matt-damon';

@Component({
  templateUrl: 'build/pages/home/home.html',
  pipes: [MattDamon]
})
export class HomePage {

  myString: any;

  constructor() {
    this.myString = "Pipes are super cool";
  }
}

Notice that we are now importing the pipe, and we also declare it in the @Component decorator (just like we need to do for directives). We’ve also added some data inside our constructor so that we will be able to use that within our template.

All that is left to do now is to use it in the template.

Modify home.html to reflect the following:

<ion-header>
 <ion-navbar>
  <ion-title>Tab 1</ion-title>
 </ion-navbar>
</ion-header>

<ion-content padding>
  <h2>Welcome to Ionic!</h2>
  <p>
    {{myString | mattDamon}}
  </p>
</ion-content>

If you take a look at the app now you should be able to see our totally useless pipe in action:

Ionic 2 Pipes Screenshot

Summary

This was a pretty simple example, but that’s pretty much all you need to know about pipes. You can make the pipe itself much more complex, but the general idea is that you pass some data in and pass some different data back out. The pipe we created was obviously a bit silly, but here’s a few example of where a pipe might come in really handy:

  • Converting dates or times to a specific format
  • Formatting addresses
  • Detecting if a value meets certain criteria

I mentioned before that we could modify the Matt Damon pipe to be able to use anybody’s name that is supplied as an argument to the pipe, but I never showed you how to do it. If pipes are a new concept to you, it’d be a worthwhile exercise to try and implement this by yourself.

What to watch next...

  • Luís Cunha

    Very useful article, I use pipes quite often and this will come in handy when the switch to ionic 2 comes.

    • victorL

      I was wondering: can’t we just define a function to do the piping? Is it because pipe is defined globally?

      Can you give an example a regular function cannot handle?

  • Joshua Paul McKearin

    Any idea how to make pipes available application-wide?
    https://forum.ionicframework.com/t/how-to-make-custom-pipes-application-wide/42843

  • Pingback: High Performance List Filtering in Ionic 2 | joshmorony - Build Mobile Apps with HTML5()

  • iantearle

    Current RC0 I get “The pipe ‘safe’ could not be found” Any ideas?

  • Brother Bill

    This fails with release Version of ionic 2 and latest Angular 2.

    Unhandled Promise rejection: Template parse errors:
    The pipe ‘mattDamon’ could not be found (” get lost, the docs will be your guide.

    [ERROR ->]
    {{myString | mattDamon}}

    “): [email protected]:5 ; Zone: ; Task: Promise.then ; Value: Error: Template parse errors:

  • Meaghan Jones

    Thank you! I just used this in an Ionic 2 app, and it worked for me! I am having a little trouble because I want to put ion-icons in place of the string Matt Damon….

  • ismaail

    if you get this error:
    Argument of type ‘{ selector: string; templateUrl: string; pipes: typeof MattDamon[]; }’ is not assignable to parameter of type ‘Component’.
    Object literal may only specify known properties, and ‘pipes’ does not exist in type ‘Component’.

    Instead of adding the pipe in pipes[] array in the @component,
    add the pipe in the ‘declarations’ array inside ‘app.modules.ts’, and no need to use ‘pipes’ array

    • yatash

      can u explain it how

      • ismaail

        If you mean how I got this error,
        I followed the same steps in this tutorial,
        in package.json, I have @angular:2.1.1 and ionic-angular:2.0.0-rc.3

        If the solution is not clear enought,
        in the file ‘app.module.ts’
        1. import the pipe
        2. add it inside the ‘declarations’ array

      • Kass Jac

        Same error here, any suggestions ?

  • John Alvir Bismonte

    Hi Josh, this article needs an update already.

    Thanks!

    • Jess Mark Panadero

      Thanks for your comment you save my day

    • John Christian Lønningdal

      Thanks for this reply. Josh should edit his article to reflect the changes in Ionic2 now. Pipes are very useful for example for enumerating keys in an object and iterate over those to simply create lists or tables.

    • Jeremy Lopez

      Thanks for this! I was beginning to think I was hopeless

  • OanaLivia

    Hello and thanks for the great article. I have a question concerning arguments passed to pipes.

    In my class definition home.ts I have a class member
    currency: string
    which reflects the users choice of currency (euro, usd, other …)
    I have a pipe price.ts, which formats the price (float with two decimals) for now. However, I want to add the the currency to the formatting.

    What is the exact syntax to use in home.html to provide the pipe with the correct value ?

    This is what I have :
    {{ item.totalAmount | price: ??? }}

    ??? = should be replaced by the evaluation of the currency member in home.ts

    {{ item.totalAmount | price: currency }} – This says currency is undefined….

    Thank you

  • gsuite

    Since RC6, all Directives and Pipes should be moved to module’s declarations.

    @NgModule({
    imports: […],
    declarations: [
    //you insert your Components, Directives and Pipes here
    ],
    bootstrap: […],
    providers: […]
    })

    export class AppModule { }

  • Louis R

    Hi,
    thanks for the article.
    Is it possible to use these Pipes with the component logic in Typescript (not in the template), like we were doing in Angular 1 with $filter(‘customFilter’, …) ?
    Thanks

  • Francisco Vieira

    How to I use a pipe (or a filter) on an input text field to transform the first letter to uppercase (or all letters)? Is it the same way? Because I have a pipe here and when I set it like this:

  • saykopat 1001

    hey your are the BEST JOSH 😀 😀 !!!!