Angular provides pipes which are one of the simplest yet most powerful tools for transforming data in the templates. Pipes allow you to take data in one form and display it in another form to improve readability.
When developing applications, it is important to know about the types of pipes Angular provides - pure and impure pipes. Understanding the distinction between these two types is crucial because it has a significant impact on the performance of your application, especially when dealing with large data sets or complex calculations.
This blog explores the key differences between pure and impure pipes in Angular, complete with examples, use cases, and performance considerations.
Pipes are a simple way to transform and format data within templates. A pipe takes in data as input and transforms it into a desired output. Angular provides several built-in pipes like CurrencyPipe, DatePipe, UpperCasePipe, LowerCasePipe and PercentPipe etc. Additionally, you can create your own custom pipe for specific transformations as per requirement.
Pipes are defined using the pipe “|” symbol.
We can apply two formats to single data by chaining pipes. A chained pipe is when the output of the first pipe is input to the next pipe.
Here’s an example of how you can use a built-in pipe :
html
// include a required pipe by adding "|" symbol
<p>Today is {{ today | date:'fullDate' }}</p>
<p>Price is {{ price | currency: 'INR' }}</p>
In this example, the date pipe transforms today's value into a more readable format, like "Thursday, September 19, 2024" and the currency pipe transforms the value into Indian rupee format like "₹4300".
A pure pipe is the default type of pipe in Angular. These pipes are recalculated only when their input data changes based on reference checks (for objects and arrays) or value checks (for primitive data types). Pure pipes are stateless, meaning they don’t depend on or alter their internal state. Angular optimizes their execution, making them ideal for simple transformations where data changes infrequently.
Recalculation on change detection: Angular only recalculates the pipe when the input value or object reference changes.
Efficient for static or rarely changing data: Pure pipes are efficient when used with immutable data structures or when data does not change frequently.
Default behavior: All pipes in Angular are pure by default unless explicitly set to impure.
Optimized performance: enhance performance by reducing frequent change detection cycles triggered.
Here’s a basic example of a custom pure pipe that converts a string to uppercase:
typescript
import { Pipe, PipeTransform } from '@angular/core';
// default set to pure type.
@Pipe({
name: 'pureUppercase'
})
export class PureUppercasePipe implements PipeTransform {
transform(value: string): string {
console.log('Pure Pipe Called');
return value.toUpperCase();
}
}
Usage in the template:
html
<p>{{ 'hello world' | pureUppercase }}</p>
In this example, the pureUppercase pipe will transform the string 'hello world' to 'HELLO WORLD'. The pipe is pure, so it will only re-execute if the input string changes.
Pure pipes are well-suited for the following use cases:
Formatting of data such as date, currency, or numbers.
Simple, stateless transformations.
Scenarios where data changes infrequently (e.g. static or immutable data).
Performance optimization where recalculation of the pipe should be minimal.
Angular’s built-in CurrencyPipe is an excellent example of a pure pipe:
html
<p>{{ 'hello world' | titlecase }}</p>
In this example, the Titlecase pipe will transform the string 'hello world' to 'Hello World'. The pipe is pure, so it will only re-execute if the input string changes.
An impure pipe, as the name suggests, is recalculated every time change detection runs, regardless of whether the input data has changed. This means Angular will invoke the pipe’s transform method every time something happens in the application—whether or not the pipe’s input has changed. Impure pipes are typically used when the pipe’s output depends on data that might change for reasons other than input reference, such as external state, mutable objects, or asynchronous data.
Recalculated on every change detection cycle: Impure pipes are recalculated every time the Angular change detection cycle is triggered, which can impact performance.
Used for dynamic and mutable data: Impure pipes are ideal for scenarios where the input is mutable, such as arrays that can change in place or objects whose internal properties change without changing the reference.
Explicit declaration: To make a pipe impure, you must set the pure property to false in the pipe’s decorator.
Here’s an example of an impure pipe that filters an array:
typescript
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'impureFilter',
pure: false
})
export class ImpureFilterPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if (!items || !searchText) {
return items;
}
return items.filter(
item => item.name.toLowerCase().includes(searchText.toLowerCase()));
}
}
Usage in the template:
html
<ul>
<li *ngFor="let item of items | impureFilter:searchText">{{ item.name }}</li> </ul>
In this example, the impureFilter pipe filters an array based on a search string. Since the pipe is impure, it will be re-executed every time change detection runs, ensuring that any changes to the items array are reflected immediately.
Impure pipes are useful in the following scenarios:
When you are dealing with mutable data, such as objects or arrays that are modified in place.
When your pipe transformation depends on some external data or asynchronous operations.
Real-time filtering or sorting of dynamic data sets.
Situations where recalculation is necessary, even if the input reference does not change.
Angular’s built-in JsonPipe is an impure pipe. It serializes objects into JSON strings for display in the template:
html
<pre>{{ someObject | json }}</pre>
Because JsonPipe is impure, it will update whenever the internal properties of someObject change, ensuring that the displayed JSON string remains up to date
pure and impure pipes behave differently when used with immutable data types such as arrays and objects.
html
<div> age : {{ user.birthDate | agePipe }} </div>
typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
user = { name:'Rohit', birthDate: '12-02-1998'};
}
function updateUser() {
this.user.birthDate = '12-05-2002' // update the birthDate property
}
We are updating the 'birthDate' property of the user object by mutating an object directly (i.e. without changing reference) which has passed to 'agePipe'. let's see how pure and impure pipes behave in this case.
typescript
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'agePipe',
pure: true
})
export class agePipe implements PipeTransform {
transform(dateString: number): any[] {
today = new Date();
birthDate = new Date(dateString);
age = today.getFullYear() - birthDate.getFullYear();
return age;
}
}
since the pipe is pure it will not recalculate the value on mutating the object directly and result will not be updated on value change. to trigger the change detection we must update the value of object by changing the reference.
function updateUser() {
this.user = {
...this.user, birthDate = '12-05-2002'
};
}
as the object is reassigned with a new value pure pipe will detect the change and update the value.
typescript
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'agePipe',
pure: false
})
export class agePipe implements PipeTransform {
transform(dateString: number): any[] {
today = new Date();
birthDate = new Date(dateString);
age = today.getFullYear() - birthDate.getFullYear();
return age;
}
}
Since the pipe is impure, mutating the object without change in reference will also update the result value in a pipe. this will also trigger every change detection cycle and slow down the application's performance.
Since pure pipes are recalculated only when the input reference changes, they are highly efficient and suitable for performance-critical applications. They work well with immutable data structures, where the reference changes only when the data is modified. This makes them ideal for:
Large data sets with infrequent changes.
Components that do not require constant re-evaluation of data.
Optimized template rendering in Angular.
Impure pipes, on the other hand, can negatively impact performance, especially if they involve complex operations. Since they are recalculated on every change detection cycle, they can slow down your application, particularly in large or complex components. However, impure pipes are necessary when dealing with:
Real-time data updates.
Asynchronous data (e.g. WebSocket messages or API responses).
Mutable data structures like arrays or objects.
By carefully choosing between pure and impure pipes, you can optimize both the performance and functionality of your Angular application. Use pure pipes when possible, and reserve impure pipes for situations where recalculation on every change detection cycle is necessary.
To effectively implement pure pipes in Angular, you will need to hire expert Angular developers who have the knowledge and experience of critical tasks in Angular. Angular Minds has an expert team of Angular developers who can do this for you.
Get in touch to know more!
This website uses cookies to analyze website traffic and optimize your website experience. By continuing, you agree to our use of cookies as described in our Privacy Policy.