Angular Custom Pipe Example
June 18, 2020
This page will walk through Angular custom pipe example. We can write our own custom pipe and that will be used in the same way as angular built-in pipes. To create custom pipe, angular provides Pipe
and PipeTransform
interfaces. Every pipe is decorated with @Pipe
where we define the name of our custom pipe. Every pipe will implement PipeTransform
interface. This interface provides transform()
method and we have to override it in our custom pipe class. transform()
method will decide the input types, number of arguments and its types and output type of our custom pipe. We perform the following steps to create a custom pipe.
Step 1: Create a typescript class.
Step 2: Decorate the class using
@Pipe
.
Step 3: Implement
PipeTransform
interface.
Step 4: Override
transform()
method.
Step 5: Configure the class in application module with
@NgModule
.
Step 6: Ready to use our custom pipe anywhere in application.
On the basis of change detention, angular provides two types of pipes.
Pure pipe: This will run only for pure changes in component properties.
Impure pipe: This will run for any type of changes in component properties.
Pure and impure pipe are declared using
@Pipe
decorator. Here on this page we will create custom pipes with and without arguments. We will also create custom pipe using angular built-in pipes. We will also provide example of pure and impure pipe. Now find the angular custom pipe tutorial with examples step by step using TypeScript.
Contents
- Software Used
- Diagram to Create Custom Pipe
- Create Component and Module
- @Pipe Decorator and PipeTransform Interface
- Create Simple Custom Pipe
- Pass Arguments in Custom Pipe
- Use Built-in Pipe in Custom Pipe
- Chaining of Custom Pipes
- Pure and Impure Custom Pipe and Change Detection
- Run Application
- Reference
- Download Source Code
Software Used
Find the software used in our demo.1. Angular 9.1.11
2. Node.js 12.5.0
3. NPM 6.9.0
Diagram to Create Custom Pipe
Here we are creating a custom pipe named as myjson. This will convert a given object input into JSON format. Our pipe will accept input of any type of object. Our custom pipe will accept two arguments. Find the demo by diagram.
1. Create a typescript class, for example
MyJSONPipe
and import Pipe
and PipeTransform
interface.
2. Decorate class using
@Pipe
and assign pipe name to name
metadata for example myjson .
3. Implement
PipeTransform
interface and override transform()
method.
4. Our custom pipe needs two arguments. So
transform()
method has three parameters. First parameter is for pipe input and the rest two is for pipe arguments.
5. In
transform()
method first parameter is of any
type, so myjson pipe will accept any type of object as an input.
6. In
transform()
method, second parameter is of number type. This will be used to decide whether myjson pipe will give pretty print output or not. If its value is 0, then no pretty print and if 1 or greater than 1, then result will be pretty print when using myjson pipe with <pre> tag.
7. In
transform()
method, third parameter provide the fields of input object that will be involved in JSON output.
8. We are using return type of
transform()
method as string, so myjson will give output as string.
9. In
transform()
method second and third parameter is optional. If we do not provide any argument to myjson pipe then all the fields will be involved in JSON format and the output will be no pretty print.
Create Component and Module
Find the component that is using our custom pipes.custompipe.component.ts
import {Component} from '@angular/core'; import {Person} from './person'; import {Company} from './company'; @Component({ selector: 'app-root', template: ` <h3>1. Using welcome Pipe</h3> {{person.name | welcome}} <br/> <h3>2. Using strformat Pipe</h3> {{message | strformat:'+'}} <h3>3. Using division Pipe</h3> <div>Dividend: <input [(ngModel)]="dividend"> </div> <div>Divisor: <input [(ngModel)]="divisor"> </div> <p> Division Result: {{dividend | division: divisor}} </p> <h3>4. Using repeat Pipe</h3> {{person.name | repeat:10}} <h3>5. Using myjson Pipe</h3> <pre>{{person | myjson}}</pre> <pre>{{person | myjson:0:'id,age'}}</pre> <pre>{{person | myjson:1:'id,name'}}</pre> <h3>6. Using myuppercaseone and myuppercasetwo Pipe</h3> {{message | myuppercaseone}} <br/> {{message | myuppercasetwo:'+'}} <br/> <h3>7. Chaining of Custom Pipes</h3> {{person.name | repeat:5 | myuppercaseone}} <h3>8. Using Pure and Impure Pipe</h3> Company Name: <input [(ngModel)] ="compName"/> {{compName}} <br/>Location: <input [(ngModel)] ="compLocation"/> {{compLocation}} <br/><br/><button (click)="updateCompany()">Update Existing</button> <button (click)="createCompany()">Create New </button> <br/><b>a. Using Pure Pipe : companyone</b><br/><br/> {{company | companyone}} <br/><br/><b>b. Using Impure Pipe : companytwo</b><br/><br/> {{company | companytwo}} ` }) export class CustomPipeComponent { //For welcome, repeat, myjson Pipe person: Person = new Person(1, 'Ram', 30); //For strformat, myuppercaseone and myuppercasetwo Pipe message: string = "My name is Mahesh"; //For division Pipe dividend : number = 23; divisor : number = 7; //For pure and impure pipe compName:string = "ABCD LTD"; compLocation:string = "Varanasi"; company = new Company(this.compName, this.compLocation); //Impure change because there is no change in object reference: company //Impure pipe will run again and Pure pipe will do nothing. updateCompany() { this.company.cname = this.compName; this.company.location = this.compLocation; } //Pure change because there is change in object reference: company //Impure pipe and Pure pipe both will run again. createCompany() { this.company = new Company(this.compName, this.compLocation); } }
company.ts
export class Company { constructor(public cname:string, public location:string) { } }
export class Person { constructor(public id:number, public name:string, public age:number) { } }
app.module.ts
import {NgModule} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {FormsModule} from '@angular/forms'; import {CustomPipeComponent} from './custompipe.component'; import {WelcomePipe} from './welcome.pipe'; import {StrFormatPipe} from './strformat.pipe'; import {MyUppercaseOnePipe} from './myuppercaseone.pipe'; import {MyUppercaseTwoPipe} from './myuppercasetwo.pipe'; import {DivisionPipe} from './division.pipe'; import {RepeatPipe} from './repeat.pipe'; import {MyJSONPipe} from './myjson.pipe'; import {CompanyOnePipe} from './companyone.pipe'; import {CompanyTwoPipe} from './companytwo.pipe'; @NgModule({ imports: [BrowserModule, FormsModule], declarations: [WelcomePipe, StrFormatPipe, MyUppercaseOnePipe, MyUppercaseTwoPipe, DivisionPipe, RepeatPipe, MyJSONPipe, CompanyOnePipe, CompanyTwoPipe, CustomPipeComponent], bootstrap: [CustomPipeComponent] }) export class AppModule { }
@Pipe Decorator and PipeTransform Interface
To create custom pipe we need to understand angularPipe
and PipeTransform
API.
@Pipe Decorator
@Pipe
decorator is a Pipe
interface. A typescript class is decorated by @Pipe
to create an angular custom pipe. Find the Pipe
interface from the angular Pipe API document.
interface Pipe { name : string pure : boolean }
pure: Assign true or false. Default is true. If true then pipe will be a pure pipe otherwise impure pipe. So by default all pipes are pure pipe.
For example we will use
Pipe
interface as @Pipe
decorator as follows.
@Pipe({ name: 'welcome' })
welcome
and as we know that by default pure metadata value is true, so welcome
pipe will be a pure pipe.
PipeTransform Interface
PipeTransform
is an angular interface. To create a custom pipe our typescript class has to implement PipeTransform
interface. It has been defined as follows in angular PipeTransform API document.
interface PipeTransform { transform(value: any, ...args: any[]) : any }
transform()
has been defined. It accepts minimum one argument and maximum any number of arguments. The parameter type is any
. It means we can pass any type of object. transform()
method returns value of type any
. To create custom pipe our typescript class will implement PipeTransform
and override transform()
method. The use of parameters is as follows.
1. First parameter (value: any): This is the value in left side of our pipe operator (|).
2. Optional parameters: These are arguments used with pipe in right side of pipe operator (|).
3. Value returned by method: This is the value that is the output of our custom pipe.
Create Simple Custom Pipe
Now we will start creating our custom pipe. Here we will create a simple custom pipe named as welcome. The syntax is as follows.string_expression | welcome
We will pass a person name for string_expression as string and output will be a welcome message. Now follow the steps to create our welcome pipe.
step 1: Create a typescript class named as
WelcomePipe
.
step 2: Import
Pipe
and PipeTransform
interface from angular core module.
step 3: Decorate
WelcomePipe
with @Pipe
. Its name metadata will define custom pipe name.
step 4:
WelcomePipe
will implement PipeTransform
interface.
step 5: Override
transform()
method of PipeTransform
interface. The parameter of transform()
can be of any type. In our example we are using string data type and return type is also a string. Here we will perform task which needs to be done by our custom pipe and return the result. This is the result which will be returned by custom pipe.
step 6: To make custom pipe available at application level, declare
WelcomePipe
in @NgModule
decorator. In our example module file is module.ts
.
Find the
WelcomePipe
class.
welcome.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ name: 'welcome' }) export class WelcomePipe implements PipeTransform { transform(value: string): string { let message = "Welcome to " + value; return message; } }
name
metadata of @Pipe
decorator has the value welcome
and that will be the name of our custom pipe. In our custompipe.component.ts
file we are using welcome pipe as given below.
{{person.name | welcome}}
Welcome to Ram
Pass Arguments in Custom Pipe
Now we will discuss some custom pipes that will accept arguments. To facilitate custom pipe to accept arguments we have to use optional parameters intransform()
method while creating custom pipe API. If we want one argument with custom pipe then use one optional parameter in transform()
method. If we want two arguments with custom pipe then use two optional parameters in transform()
method and so on. Now find our custom pipes that are using arguments.
1. Create strformat Custom Pipe
Find the syntax.
string_expression | strformat[:seperator]
The strformat will format the given string expression. The spaces between words will be replaced by given separator. Now find the typescript class
StrFormatPipe
that will create strformat pipe.
strformat.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ name: 'strformat' }) export class StrFormatPipe implements PipeTransform { transform(value: string, seperator: string): string { let result = value.split(' ').join(seperator); return result; } }
name
metadata of @Pipe
decorator has the value strformat
and that will be the name of our custom pipe. We will observe that in transform()
method first parameter is a string and this will be used by string_expression. Second parameter is also a string and this will be used by strformat
pipe to pass arguments. In our example argument is string value given by separator. Now transform()
method has return type as string, so the output of our pipe strformat will be a string.
In our
custompipe.component.ts
file we are using strformat pipe as given below.
{{message | strformat:'+'}}
My+name+is+Mahesh
Using division custom pipe we will divide a number by a given number. Find the syntax.
number_expression | division[:num_divisor]
Find the description.
number_expression : An expression that will return a number and that will be dividend.
num_divisor: This number is the argument of our pipe that will be used as divisor.
Now find the typescript class
DivisionPipe
that will create division pipe.
division.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ name: 'division' }) export class DivisionPipe implements PipeTransform { transform(dividend: number, divisor: number): number { let num = dividend / divisor; return num; } }
@Pipe
decorator. Here custom pipe name is division. In transform()
method, there are two parameters of number type. First parameter is for expression used with pipe operator and second parameter is used for pipe argument. Return type of method is also a number, so division pipe operator will give output as number.
In our
custompipe.component.ts
file we are using division pipe as given below.
<div>Dividend: <input [(ngModel)]="dividend"> </div> <div>Divisor: <input [(ngModel)]="divisor"> </div> <p> Division Result: {{dividend | division: divisor}} </p>

3. Create repeat Custom Pipe
We are creating a repeat pipe. This pipe will repeat a given word. This will be repeated as many times as given frequency. Find the syntax.
string_expression | repeat[:frequency]
Find the typescript class
RepeatPipe
that will create repeat pipe.
repeat.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ name: 'repeat' }) export class RepeatPipe implements PipeTransform { transform(word: string, frequency: number): string { let cnt = 1; let strResult= word; while (cnt < frequency) { strResult = strResult + ' ' + word; cnt = cnt + 1; } return strResult; } }
@Pipe
decorator has defined the pipe name as repeat. The method transform()
has two parameters. One is of string type and second is of number type. First parameter is for string_expression and second parameter is for frequency.
In our
custompipe.component.ts
file we are using repeat pipe as given below.
{{person.name | repeat:10}}
Ram Ram Ram Ram Ram Ram Ram Ram Ram Ram
Here we are creating myjson custom pipe. This pipe will convert an expression into JSON format. It will accept two arguments. Find the syntax.
expression | myjson[:prettyprint[:fields]]
Find the description.
expression : Expression that will be converted into JSON format. It can be primitive data type or any object.
prettyprint : If the value is 0, then no pretty print and if the value is 1 or greater than 1, then we will get pretty print JSON format.
fields : If no fields are provided then all the fields of object will take part in JSON format, if specified then only those fields will take part in JSON format.
If no argument is passed then myjson will convert the given object into JSON format with all fields and without pretty print. Now find the typescript class
MyJSONPipe
that will create myjson pipe.
myjson.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; @Pipe({ name: 'myjson' }) export class MyJSONPipe implements PipeTransform { transform(value: any, prettyprint?: number, fields?: string): string { let array = (fields == null? null : fields.split(',')); let pp = (prettyprint == null ? 0 : prettyprint); let result = JSON.stringify(value, array, pp); return result; } }
@Pipe
decorator. The method transform()
has three parameters. First parameter is of any
type. It means any type of object can be passed to convert into JSON format. The rest two parameters are pipe arguments. Pretty print of JSON format also requires <pre> tag while using myjson pipe.
In our
custompipe.component.ts
file we are using myjson pipe as given below.
<pre>{{person | myjson}}</pre> <pre>{{person | myjson:0:'id,age'}}</pre> <pre>{{person | myjson:1:'id,name'}}</pre>
{"id":1,"name":"Ram","age":30} {"id":1,"age":30} { "id": 1, "name": "Ram" }
Use Built-in Pipe in Custom Pipe
Custom pipe can also use angular built-in pipe such as DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, and PercentPipe. In our example we will create myuppercaseone and myuppercasetwo pipe. Both pipes will useUpperCasePipe
built-in pipe. There are two ways to use UpperCasePipe
in our custom pipes.
1. Extending
UpperCasePipe
built-in pipe class:UpperCasePipe
is an angular built-in pipe. It implements PipeTransform
interface and override transform()
method as we do in our custom pipes. Here we will create our custom pipe class named as MyUppercaseOnePipe
. This time our class MyUppercaseOnePipe
will not implement PipeTransform
because it will extend UpperCasePipe
built-in pipe and that is already implementing PipeTransform
interface. Now find the MyUppercaseOnePipe
class.
myuppercaseone.pipe.ts
import {Pipe} from '@angular/core'; import {UpperCasePipe} from '@angular/common'; @Pipe({ name: 'myuppercaseone' }) export class MyUppercaseOnePipe extends UpperCasePipe{ transform(value: string): string { let result = super.transform(value); result = result.split(' ').join('-'); return result; } }
UpperCasePipe
is the API of CommonModule
, so we need to import UpperCasePipe
class from angular common package. Here we are overriding transform()
method from UpperCasePipe
, so we cannot change number of parameters and types in transform()
method. Now find the line of code.
let result = super.transform(value);
super
keyword we call the parent class method. The value passed to transform()
method of MyUppercaseOnePipe
class is first processed by transform()
method of UpperCasePipe
class and then we perform our changes and then we return the final result.
In our
custompipe.component.ts
file we are using myuppercaseone pipe as given below.
{{message | myuppercaseone}}
MY-NAME-IS-MAHESH
UpperCasePipe
built-in pipe class: We can also use built-in pipe in our custom pipe by creating object of built-in pipe API. Here we will create our custom pipe as usual by implementing
PipeTransform
and within transform()
method we will use parameters and their types according to our requirements. To process the data by UpperCasePipe
pipe, we will create the object of it and pass the data to its transform()
method. Now find the MyUppercaseTwoPipe
class.
myuppercasetwo.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; import {UpperCasePipe} from '@angular/common'; @Pipe({ name: 'myuppercasetwo' }) export class MyUppercaseTwoPipe implements PipeTransform{ transform(value: string, seperator: string): string { let upipe = new UpperCasePipe(); let result = upipe.transform(value); result = result.split(' ').join(seperator); return result; } }
custompipe.component.ts
file we are using myuppercasetwo pipe as given below.
{{message | myuppercasetwo:'+'}}
MY+NAME+IS+MAHESH
Chaining of Custom Pipes
Chaining of custom pipes is using more than one pipe together. The output of first pipe will be the input for next pipe and so on. Find the example.{{person.name | repeat:5 | myuppercaseone}}
RAM-RAM-RAM-RAM-RAM
Pure and Impure Custom Pipe and Change Detection
Angular provides pure and impure pipes on the basis of change detection. Here we will discuss pure and impure pipes with examples.1. Change Detection
Angular uses a change detection process for changes in data-bound values. Change detection runs after every keystroke, mouse move, timer tick, and server response. In case of pipe, angular picks a simpler, faster change detection algorithm.
2. Pure Pipes
By default all pipes are pure pipe. Pure pipes are those pipes that have
pure: true
in @Pipe
decorator while creating pipe class. If we have not used pure
metadata then its default value will be true in @Pipe
decorator. Pure pipes executes only for pure changes in its input values.
Find the pure changes.
a. Change to a primitive input values such as String, Number, Boolean.
b. Change to object reference of Date, Array, Function, Object.
Above changes are pure changes. If the input values used with pure pipe, comes under the pure changes then pipe will run again to give output accordingly. Pure pipe is created as follows.
@Pipe({ name: 'companyone' })
@Pipe
decorator is using pure: true
.
3. Impure Pipes
Impure pipes will run for every component change detection cycle. So it is obvious that impure pipes will also run for pure changes. Impure pipe will run for every keystroke or mouse move. So the conclusion is that impure pipe will run a lot and hence we should take care while using impure pipe because it may reduce performance of the application and can destroy user experience. Impure pipe is created as follows.
@Pipe({ name: 'companytwo', pure: false })
pure
has been assigned with false boolean value.
4. Example of Pure and Impure Pipes
Now we will discuss an example of pure and impure pipe. We will see that pure pipe will run only for pure changes whereas impure pipe will run for every type of changes in component properties. We will start by creating pure and impure pipes whose
transform()
method will use Company
class as parameter type and string
as return type.
Find the pure pipe named as companyone
companyone.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; import {Company} from './company'; @Pipe({ name: 'companyone' }) export class CompanyOnePipe implements PipeTransform { transform(obj: Company): string { let output = obj.cname+' : '+ obj.location; return output; } }
companytwo.pipe.ts
import {Pipe, PipeTransform} from '@angular/core'; import {Company} from './company'; @Pipe({ name: 'companytwo', pure: false }) export class CompanyTwoPipe implements PipeTransform { transform(obj: Company): string { let output = obj.cname+' : '+ obj.location; return output; } }
Now we will code scenarios for pure and impure changes in
Company
object. Suppose we have created Company
object as follows.
compName:string = "ABCD LTD"; compLocation:string = "Varanasi"; company = new Company(this.compName, this.compLocation);
company
object by changing its reference: To change the reference we will create a new object of Company
class and assign it to component property company
as follows.
createCompany() { this.company = new Company(this.compName, this.compLocation); }
b. Impure change in
company
object by updating its property values: To generate the scenario of impure change, we will update the property value of our company
object as follows.
updateCompany() { this.company.cname = this.compName; this.company.location = this.compLocation; }
company
object.
Now find the below code from
custompipe.component.ts
file.
Company Name: <input [(ngModel)] ="compName"/> {{compName}} <br/>Location: <input [(ngModel)] ="compLocation"/> {{compLocation}} <br/><br/><button (click)="updateCompany()">Update Existing</button> <button (click)="createCompany()">Create New </button> <br/><b>a. Using Pure Pipe : companyone</b><br/><br/> {{company | companyone}} <br/><br/><b>b. Using Impure Pipe : companytwo</b><br/><br/> {{company | companytwo}}
Initially both text box will be populated with following values.
Company Name : ABCD LTD
Location: Varanasi

Case 1: Change the text box values as follows.
Company Name : ABCD LTD11
Location: Varanasi11
Now click on Update Existing button. Output of companyone pipe will be as follows.
ABCD LTD : Varanasi
ABCD LTD11 : Varanasi11
updateCompany()
will execute and performs impure change in company
object. So only impure pipe companytwo will run again and change its output. There will be no change in pure pipe companyone output because it has not run again due to impure change in company
object.
Case 2: Change the text box values as follows.
Company Name : ABCD LTD1111
Location: Varanasi1111
Now click on Create New button. Output of companyone pipe will be as follows.
ABCD LTD1111 : Varanasi1111
ABCD LTD1111 : Varanasi1111
createCompany()
will execute and performs pure change in company
object. So this time pure and impure pipe both will run again. It means companyone and companytwo both pipe will run again and change its output.
Run Application
To run the application, find the steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
3. Run ng serve using command prompt.
4. Access the URL http://localhost:4200
Find the print screen of the output.

I am done now. Happy angular learning!