Hey there!
As an experienced Angular developer, I want to share everything I‘ve learned about one of the most useful Angular features – pipes.
Pipes transform your output data into beautiful, readable formats right in your templates. Once you master pipes, you‘ll wonder how you ever lived without them!
In this comprehensive guide, you’ll learn:
- Why pipes are so invaluable in Angular apps
- How built-in pipes solve common formatting needs
- How to create custom pipes for unique data transformations
- Patterns for supercharging your pipes
- When to use pure vs impure pipes
- Pipe best practices used by the pros
Follow along and you’ll gain the skills to build custom pipes for clean, elegant data display like a pro!
Why Pipes are Indispensable in Angular
Pipes provide a way to declare display-value transformations right in your templates. For example:
<!-- Transform a date -->
{{ birthday | date }}
<!-- Format as currency -->
{{ price | currency }}
This is much cleaner than declaring formatting functions in your components!
According to the 2021 State of JavaScript survey, Angular ranks 3rd among front-end frameworks with 67.4% awareness.
As an Angular developer, mastering pipes will level up your skills in how to cleanly transform data in your apps.
Here are some of my favorite reasons to use pipes:
They Abstract Away Formatting Logic
Without pipes, you‘d have to declare formatting functions in your components like:
formatDate(date) {
// date formatting logic
}
And in your template:
{{ formatDate(birthday) }}
This clutters up your components!
With pipes, you declare the formatting logic once in a pipe, then reuse it:
{{ birthday | date }}
Much cleaner!
They Make Templates More Readable
Scanning this:
{{ formatDate(order.date) | currency | titlecase | slice:0:10 }}
You can quickly grasp what‘s happening. With pipes, you almost read it like English!
Built-in Pipes Save Time
No need to reinvent the wheel for common formats like dates and currencies – just use a built-in pipe!
You Can Chain Pipes
Use the pipe operator (|
) to combine multiple pipes:
{{ data | pipe1 | pipe2 | pipe3 }}
This unlocks powerful data transformations.
You Can Create Custom Pipes
For specialized formats, make your own custom pipes tailored to your app!
Bottom line – pipes will make your Angular skills shine ✨ by handling transformations the Angular way.
Now let‘s look at some common built-in pipes…
Built-in Pipes for Every Scenario
Angular ships with a solid set of built-in pipes covering all the common formatting scenarios:
DatePipe
The DatePipe
formats dates based on locale rules:
{{ dateObj | date }} <!-- 3/15/2022 -->
{{ dateObj | date:‘short‘ }} <!-- 3/15/22 -->
You can pass in different formatting presets like ‘short‘
, or a custom format string.
CurrencyPipe
The CurrencyPipe
formats numbers into currency strings in your locale:
<!-- USD -->
{{ 12.5 | currency }} // $12.50
<!-- EUR -->
{{ 12.5 | currency:‘EUR‘ }} // €12.50
PercentPipe
The PercentPipe
converts a number into a locale-specific percentage string:
{{ 0.25 | percent }} // 25%
LowerCasePipe / UpperCasePipe
These pipes convert text into lower or uppercase:
{{ ‘Hello‘ | uppercase }} // HELLO
{{ ‘Hello‘ | lowercase }} // hello
JsonPipe
The JsonPipe
converts any object into a nicely formatted JSON string – great for debugging!
<!-- Displays formatted JSON -->
{{ myObj | json }}
There are many more built-in pipes for common scenarios like slicing arrays, filtering, and async values.
These will cover most simple formatting needs, but for specialized transformations it‘s time to build your own custom pipe…
Creating Your Own Custom Pipe
One of Angular’s killer features is the ability to create your own pipes tailored to your app’s unique data formats.
Building a custom pipe is easy – just follow these steps:
1. Generate the Pipe with the CLI
Use the Angular CLI to generate a new pipe skeleton:
ng generate pipe my-custom-pipe
This creates:
- my-custom-pipe.pipe.ts – The pipe class code
- my-custom-pipe.pipe.spec.ts – Unit test file
The CLI gives you a head start!
2. Import the Pipe
Decorator
In the generated .ts
file, import the required Pipe
decorator:
import { Pipe, PipeTransform } from ‘@angular/core‘;
This provides the decorator and interface we need to build a working pipe.
3. Add the @Pipe
Decorator
Above the pipe class, add the @Pipe
decorator like:
@Pipe({
name: ‘myCustomPipe‘
})
This tells Angular this class is a pipe with the given name.
4. Implement the PipeTransform
Interface
Next have your pipe class implement the PipeTransform
interface:
export class MyCustomPipe implements PipeTransform {
// Our transform method
}
This enforces that your class has a transform()
method.
5. Write the Transform Method
Here is where you define the pipe’s transformation logic:
transform(value: any) {
// Transform value
return transformedValue;
}
The value
argument is the input to the pipe, and it returns the transformed value.
For example, a pipe that capitalizes strings:
transform(value: string): string {
return value.toUpperCase();
}
6. Add the Pipe to the Module
Finally, register your pipe in the declarations
array of your app module so Angular knows about it:
@NgModule({
declarations: [
AppComponent,
MyCustomPipe
]
})
Once added here, you can use your pipe anywhere in your app!
And that’s really all there is to it! Let’s walk through an example.
Custom Pipe Example
Let’s build a pipe that formats a username by truncating it after 8 characters.
First generate it:
ng generate pipe truncate
In truncate.pipe.ts
:
import { Pipe, PipeTransform } from ‘@angular/core‘;
@Pipe({
name: ‘truncate‘
})
export class TruncatePipe implements PipeTransform {
transform(value: string): string {
// Truncate value after 8 chars
return value.substring(0, 8) + ‘...‘;
}
}
The transform:
- Takes the input value
- Truncates it after 8 chars
- Adds ‘…‘ at the end
In the module:
@NgModule({
// ...
declarations: [
TruncatePipe
]
})
Then in a template:
<!-- Truncates the username -->
<p>{{ user.name | truncate }}</p>
Just like that, we‘ve created a reusable pipe to truncate long usernames!
Power-up Your Pipes
Beyond basic data transforms, here are some advanced patterns to take your pipes to the next level:
Parameterize Them
You can pass arguments to make pipes more configurable:
transform(value: string, limit: number): string {
return value.substring(0, limit);
}
Used like:
{{ user.name | truncate:15 }}
Chain Pipes
Use the |
operator to compose pipes:
{{ birthday | date | uppercase }}
This chains the DatePipe
and UpperCasePipe
.
Create Stateful Pipes
You can even give pipes state by storing values on the class:
items = [];
transform(value: any) {
// filter value based on saved items
}
Useful for things like filtering.
Make Async Pipes
Use async pipes to work with promises and observables:
transform(value: Observable) {
return value.pipe(map(data => {
// transform data
}))
}
This unlocks asynchronous capabilities!
The sky‘s really the limit once you master building pipes. They let you declaratively transform data in your templates any way you need.
Next let‘s compare pure and impure pipes…
Pure vs Impure Pipes
There are two categories of pipes in Angular:
Pure Pipes
Pure pipes are the default when using the @Pipe
decorator.
A pure pipe is only called by Angular when the input value reference changes.
For example, if user.name
stays the same, a pure pipe won‘t re-evaluate.
This allows Angular to optimize performance and avoid unnecessary transforms. All built-in pipes are pure.
Impure Pipes
An impure pipe is called on every change detection cycle regardless if the input changed.
Impure pipes are useful when you need to access something imperative like the DOM, Browser API, or external REST API.
For example, an impure pipe that calls a REST API:
@Pipe({
name: ‘apiData‘,
pure: false
})
transform(endpoint) {
return http.get(endpoint).pipe(
map(data => {
// Transform data
})
)
}
To define a pipe as impure, set pure: false
:
@Pipe({
name: ‘impurePipe‘,
pure: false
})
In general, prefer pure pipes for performance unless you need impure behavior.
Now let‘s look at some best practices when working with pipes.
Pipe Best Practices
Here are some best practices I‘ve learned for working effectively with pipes:
-
Naming – Use camelCase names like
myCustomPipe
-
Single responsibility – Each pipe should do one thing, keeping logic clean.
-
DRY – Reuse common pipes instead of duplicating.
-
Pure over impure – Favor pure pipes for performance, only impure when needed.
-
Unit test – Thoroughly unit test all pipes.
-
NgModule declaration – Remember to declare custom pipes.
-
No side effects – A pipe should be free of side effects and return the same value for the same input.
-
Idempotent – Pipes should be idempotent, producing the same output for duplicate calls.
-
Business logic in services – Move complex logic out of pipes into services.
Following these practices will ensure you get the most out of pipes!
Pipe FAQs
Here are answers to some frequently asked questions about pipes:
Why are pipes useful in Angular?
Pipes transform output data into a readable, consumable format for display in the UI. They encapsulate formatting logic in a reusable way.
What‘s the difference between built-in and custom pipes?
Built-in pipes like DatePipe cover common formatting scenarios. Custom pipes allow you to create application-specific transformations not covered by the built-ins.
How do you pass arguments to a pipe?
Use the colon syntax for arguments like:
{{ value | pipe:arg1:arg2 }}
What is the difference between pure and impure pipes?
Pure pipes only run when the input value changes while impure pipes run on every change detection cycle.
How do you chain pipes together?
Use the pipe operator (|
) to chain like:
{{ value | pipe1 | pipe2 }}
The pipes execute left-to-right, passing the output of one to the input of the next.
Should pipes have side effects?
No, pipes should be free of side effects and return the same value for the same input to avoid bugs.
I hope these FAQs help clear up some common questions around pipes!
Summary
Here‘s a quick recap of what we covered:
- Pipes encapsulate display-value transformations in a declarative & reusable way.
- Built-in pipes like DatePipe and CurrencyPipe handle common formatting needs.
- You can create custom pipes for unique data transformations.
- Pipe chaining composes multiple pipes.
- Pure pipes are optimal for performance.
- Follow best practices like single responsibility to avoid issues.
Pipes are one of Angular‘s most useful features. Mastering them will take your formatting skills to the next level!
For more Angular tips, check out these tutorials:
I hope this guide gives you the knowledge to harness the power of Angular pipes. Happy coding!