Angular Pipes: A Comprehensive guide
bytebantz
Posted on September 9, 2024
Pipes in Angular are simple functions used to transform data in templates without modifying the underlying data. Pipes take in a value, process it, and return a formatted or transformed output. They are often used for formatting dates, numbers, strings, and even arrays or objects.
They allow you to format and display data in a more readable or relevant format directly in the view without altering the underlying data model.
Using pipes helps in keeping the code clean and readable. Instead of writing complex logic in the templates or components, you can encapsulate that logic in a pipe, which can then be reused across different parts of your application.
For example, if you’re developing a blog platform where users can see the publication date of articles. Dates need to be displayed in a user-friendly format, such as “August 31, 2024,” instead of the raw format “2024–08–31T14:48:00.000Z”. With pipes, you can use Angular’s built-in DatePipe in the template instead of manually formatting the date in the component, cluttering the code and reducing readability.
<p>Published on: {{ article.publishDate | date:'longDate' }}</p>
To apply a pipe, use the pipe operator (|) within a template expression as shown in the above code example.
Built-in Pipes
Angular comes with several built-in pipes that cover common tasks (DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, AsyncPipe, JsonPipe, etc.). Knowing how to use these can make your code cleaner and more efficient.
Examples:
<pre>{{ user | json }}</pre>
<p>Price: {{ product.price | currency:'USD' }}</p>
<p>{{ user.name | uppercase }}</p>
Parametrized Pipes
Many Angular pipes accept parameters to customize their behavior.
To specify the parameter, follow the pipe name with a colon (:) and the parameter value
Some pipes accept multiple parameters, which are separated by additional colons.
Parameters can be optional or required. Suppose you have a custom pipe that formats currency and requires you to specify the currency type as a parameter. If this parameter is not provided, the pipe might not be able to format the value correctly.
<p>The product price is {{ price | customCurrency:'USD' }}</p>
1. DatePipe with Parameters
<p>Published on: {{ article.publishDate | date:'MMMM d, y, h:mm:ss a' }}</p>
This formats the date as “August 31, 2024, 2:48:00 PM”.
2. CurrencyPipe with Parameters
<p>Price: {{ product.price | currency:'EUR':'symbol-narrow':'1.0-0' }}</p>
This formats the price as “€1,235” (rounded to no decimal places).
Chaining Pipes
You can chain multiple pipes together to achieve complex transformations.
<p>{{ article.content | slice:0:100 | uppercase }}</p>
This will slice the first 100 characters of article.content and convert them to uppercase.
Custom Pipes
Sometimes, the built-in pipes may not meet your specific needs and you will need to create a custom pipe to handle the specific logic. Here’s how you can do it.
Example:
In the following example we are going to create a pipe that adds a greeting to a name like “Hello, Alice!”
Run the following command to generate a new pipe:
ng generate pipe greet
Now, let’s modify the greet.pipe.ts file in the src/app directory to include the pipe logic:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'greet', // This is the name you'll use in the template
standalone: true,
})
export class GreetPipe implements PipeTransform {
transform(value: string): string {
return `Hello, ${value}!`; // This is the transformation logic
}
}
Once your pipe is ready, you can use it in your templates.
<p>{{ 'Alice' | greet }}</p>
Creating a Parameterized Custom Pipe
Now we are going to make the greeting customizable, so you can say “Hi, Alice!” or “Welcome, Alice!” depending on what you pass to the pipe.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'greet', // Same pipe name as before
standalone: true,
})
export class GreetPipe implements PipeTransform {
transform(value: string, greeting: string = 'Hello'): string {
return `${greeting}, ${value}!`; // Now it uses the greeting passed in
}
}
The transform method now has a second parameter, greeting. If no greeting is provided, it defaults to “Hello”.
Now you can customize the greeting in your templates.
<p>{{ 'Alice' | greet:'Hi' }}</p>
<p>{{ 'Bob' | greet:'Welcome' }}</p>
Pure vs. Impure Pipes
1. Pure Pipes
By default, all Angular pipes are pure. A pure pipe only gets called when input data (like a number or a string) or when the reference to an object (like an array or date) changes. This makes pure pipes efficient and performant because the pipe doesn’t run unnecessarily.
However, if your data is more complex, like an array of items, Angular might not notice changes inside the array (like adding a new item) because the reference to the array hasn’t changed.
Unless necessary, keep your pipes pure to avoid unnecessary re-renders and to maintain performance.
Example:
@Pipe({
name: "onSale",
standalone: true,
pure: true,
})
export class OnSalePipe implements PipeTransform {
transform(items: Item[]): Item[] {
return items.filter((item) => item.isOnSale);
}
}
In your template:
<ul>
<li *ngFor="let item of (items | onSale)">
{{ item.name }} - {{ item.price | formatPrice }}
</li>
</ul>
If you add a new item to the items array that’s on sale, you might expect it to show up in the list. But if you simply push the new item into the array, the list might not update because the array reference hasn’t changed.
2. Impure Pipes
An impure pipe, on the other hand, is called every time Angular performs a change detection cycle. However, because they run so often, they can slow down your app.
Example:
@Pipe({
name: "onSaleImpure",
standalone: true,
pure: false,
})
export class OnSaleImpurePipe implements PipeTransform {
transform(items: Item[]): Item[] {
return items.filter((item) => item.isOnSale);
}
}
In your template:
<ul>
<li *ngFor="let item of (items | onSaleImpure)">
{{ item.name }} - {{ item.price | formatPrice }}
</li>
</ul>
Now, when you add a new item, the pipe will notice the change and update the list.
Best Practices for Using Pipes
Keep Pipes Simple. Avoid Heavy Computations in Pipes
Name Pipes Clearly and Descriptively
Keep Pipes Focused on a Single Responsibility
Avoid Impure Pipes When Possible
Test Custom Pipes Thoroughly
Conclusion
Angular pipes streamline data transformation tasks, making your code more modular, reusable, and maintainable. They help to enforce consistency across the application and improve the readability of your templates, which is crucial for developing scalable and maintainable applications.
Posted on September 9, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
October 31, 2024