1. Introduction
In this tutorial, we’ll discuss pure and impure pipe in Angular. Understanding pure and impure pipe is very important to writing efficient Pipes and efficient application.
By default, pipe are defined as pure in Angular which means Angular executes the pipe only when it detects a pure change to the input value. In case of primitive input value (such as String, Number, Boolean), the pure change is the change in the primitive value itself. In case changed object reference (such as Object, Array), a pure change is change in the object reference.
A pure function, for a given input, should always return the same output. A pure pipe should always use a pure function.
Let us see few examples of pure and impure change:
- If an element is added to the array, it is an impure change as the reference is the same.
- If a new array is assigned to a variable, it is pure change.
- If a property of a composite object is changed, it is an impure change.
- If a new object is assigned to the variable, it is a pure change.
It is easy for Angular to find whether the reference of the object is changed in comparison to checking the individual properties of the object. That is why the pure pipe execution is faster in comparison to impure pipe. Using an impure pipe can affect the performance of your application.
Let us understand the difference between pure and impure pipe with the help of an example.
2. Example
In this example, we’ll create a filter which filters even numbers from an array. We also have an input box and a list to show only even numbers. In input box we can provide a number, which if is an even number will be added to the list when button is clicked.
Our template is very simple.
<input type="text" [(ngModel)]="inputNum" /> <input type="button" value="Add" (click)="add()" style="margin-left: 10px" /> <ul> <li *ngFor="let num of arr | evenFilter">{{ num }}</li> </ul>
In the browser, it looks like the following:
Following is the pipe to filter even numbers:
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'evenFilter', pure: true, }) export class EvenFilterPipe implements PipeTransform { transform(numbers: number[]): number[] { console.log('pipe called'); let result = numbers.filter((num) => num % 2 === 0); return result; } }
Note that the pipe is pure.
When we provide a value in the input box and click on the add button, the number is pushed to the array. Since the pipe is pure and the array is an object, adding an even number to the array will not execute the pipe. This can be verified by checking the console as message “pipe called” will not be printed and number will not be added in the list.
So, we need to fix the code to meet our requirement. This problem can be solved in two ways.
- Instead of adding a number to the array, use a new array.
- Make the pipe as impure so that for any change in array (adding a number to array), pipe is executed.
Let us now try these two solutions.
Solution 1: Use a new array
In this approach, we create and use a new array so that the reference is changed. Since a new array is changed and pipe is pure, it will be executed. After the change, the component changes to the following:
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { title = 'pipe-example'; inputNum: any = null; arr: number[] = [1, 2, 3, 4, 5, 6]; add() { let numbersCopy = [...this.arr]; numbersCopy.push(this.inputNum); this.arr = numbersCopy; } }
Now run the code and try to enter an even number in input box and click on Add button. The even number will be added to the list in the browser.
Solution 2: Make pipe as impure
Make the pipe as impure:
@Pipe({ name: 'evenFilter', pure: false, })
This will execute the pipe for every change detection. If an element is added to the array, pipe will be executed.