{ "id": "guide/pipes", "title": "Transforming Data Using Pipes", "contents": "\n\n\n
\n mode_edit\n
\n\n\n
\n

Transforming Data Using Pipeslink

\n

Use pipes to transform strings, currency amounts, dates, and other data for display.\nPipes are simple functions you can use in template expressions to accept an input value and return a transformed value. Pipes are useful because you can use them throughout your application, while only declaring each pipe once.\nFor example, you would use a pipe to show a date as April 15, 1988 rather than the raw string format.

\n
\n

For the sample app used in this topic, see the .

\n
\n

Angular provides built-in pipes for typical data transformations, including transformations for internationalization (i18n), which use locale information to format data.\nThe following are commonly used built-in pipes for data formatting:

\n\n
\n\n
\n

You can also create pipes to encapsulate custom transformations and use your custom pipes in template expressions.

\n

Prerequisiteslink

\n

To use pipes you should have a basic understanding of the following:

\n\n

Using a pipe in a templatelink

\n

To apply a pipe, use the pipe operator (|) within a template expression as shown in the following code example, along with the name of the pipe, which is date for the built-in DatePipe.\nThe tabs in the example show the following:

\n\n\n \n<p>The hero's birthday is {{ birthday | date }}</p>\n\n\n \nimport { Component } from '@angular/core';\n\n@Component({\n selector: 'app-hero-birthday',\n template: `<p>The hero's birthday is {{ birthday | date }}</p>`\n})\nexport class HeroBirthdayComponent {\n birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based\n}\n\n\n\n\n

The component's birthday value flows through the pipe operator, | to the date function.

\n\n

Transforming data with parameters and chained pipeslink

\n

Use optional parameters to fine-tune a pipe's output.\nFor example, you can use the CurrencyPipe with a country code such as EUR as a parameter.\nThe template expression {{ amount | currency:'EUR' }} transforms the amount to currency in euros.\nFollow the pipe name (currency) with a colon (:) and the parameter value ('EUR').

\n

If the pipe accepts multiple parameters, separate the values with colons.\nFor example, {{ amount | currency:'EUR':'Euros '}} adds the second parameter, the string literal 'Euros ', to the output string. You can use any valid template expression as a parameter, such as a string literal or a component property.

\n

Some pipes require at least one parameter and allow more optional parameters, such as SlicePipe. For example, {{ slice:1:5 }} creates a new array or string containing a subset of the elements starting with element 1 and ending with element 5.

\n

Example: Formatting a datelink

\n

The tabs in the following example demonstrates toggling between two different formats ('shortDate' and 'fullDate'):

\n\n\n \n<p>The hero's birthday is {{ birthday | date:\"MM/dd/yy\" }} </p>\n\n\n \ntemplate: `\n <p>The hero's birthday is {{ birthday | date:format }}</p>\n <button (click)=\"toggleFormat()\">Toggle Format</button>\n`\n\n\n \nexport class HeroBirthday2Component {\n birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based\n toggle = true; // start with true == shortDate\n\n get format() { return this.toggle ? 'shortDate' : 'fullDate'; }\n toggleFormat() { this.toggle = !this.toggle; }\n}\n\n\n\n\n

Clicking the Toggle Format button alternates the date format between 04/15/1988 and Friday, April 15, 1988 as shown in Figure 1.

\n
\n \"Date\n
\n

Figure 1. Clicking the button toggles the date format

\n
\n

For date pipe format options, see DatePipe.

\n
\n

Example: Applying two formats by chaining pipeslink

\n

You can chain pipes so that the output of one pipe becomes the input to the next.

\n

In the following example, chained pipes first apply a format to a date value, then convert the formatted date to uppercase characters.\nThe first tab for the src/app/app.component.html template chains DatePipe and UpperCasePipe to display the birthday as APR 15, 1988.\nThe second tab for the src/app/app.component.html template passes the fullDate parameter to date before chaining to uppercase, which produces FRIDAY, APRIL 15, 1988.

\n\n \nThe chained hero's birthday is\n{{ birthday | date | uppercase}}\n\n\n \nThe chained hero's birthday is\n{{ birthday | date:'fullDate' | uppercase}}\n\n\n\n\n

Creating pipes for custom data transformationslink

\n

Create custom pipes to encapsulate transformations that are not provided with the built-in pipes.\nYou can then use your custom pipe in template expressions, the same way you use built-in pipes—to transform input values to output values for display.

\n

Marking a class as a pipelink

\n

To mark a class as a pipe and supply configuration metadata, apply the @Pipe decorator to the class.\nUse UpperCamelCase (the general convention for class names) for the pipe class name, and camelCase for the corresponding name string.\nDo not use hyphens in the name.\nFor details and more examples, see Pipe names.

\n

Use name in template expressions as you would for a built-in pipe.

\n
\n\n
\n

Using the PipeTransform interfacelink

\n

Implement the PipeTransform interface in your custom pipe class to perform the transformation.

\n

Angular invokes the transform method with the value of a binding as the first argument, and any parameters as the second argument in list form, and returns the transformed value.

\n

Example: Transforming a value exponentiallylink

\n

In a game, you may want to implement a transformation that raises a value exponentially to increase a hero's power.\nFor example, if the hero's score is 2, boosting the hero's power exponentially by 10 produces a score of 1024.\nYou can use a custom pipe for this transformation.

\n

The following code example shows two component definitions:

\n\n\n \nimport { Pipe, PipeTransform } from '@angular/core';\n/*\n * Raise the value exponentially\n * Takes an exponent argument that defaults to 1.\n * Usage:\n * value | exponentialStrength:exponent\n * Example:\n * {{ 2 | exponentialStrength:10 }}\n * formats to: 1024\n*/\n@Pipe({name: 'exponentialStrength'})\nexport class ExponentialStrengthPipe implements PipeTransform {\n transform(value: number, exponent?: number): number {\n return Math.pow(value, isNaN(exponent) ? 1 : exponent);\n }\n}\n\n\n\n \nimport { Component } from '@angular/core';\n\n@Component({\n selector: 'app-power-booster',\n template: `\n <h2>Power Booster</h2>\n <p>Super power boost: {{2 | exponentialStrength: 10}}</p>\n `\n})\nexport class PowerBoosterComponent { }\n\n\n\n\n
\n \"Power\n
\n

Figure 2. Output from the exponentialStrength pipe

\n
\n

To examine the behavior the exponentialStrength pipe in the , change the value and optional exponent in the template.

\n
\n\n

Detecting changes with data binding in pipeslink

\n

You use data binding with a pipe to display values and respond to user actions.\nIf the data is a primitive input value, such as String or Number, or an object reference as input, such as Date or Array, Angular executes the pipe whenever it detects a change for the input value or reference.

\n

For example, you could change the previous custom pipe example to use two-way data binding with ngModel to input the amount and boost factor, as shown in the following code example.

\n\nimport { Component } from '@angular/core';\n\n@Component({\n selector: 'app-power-boost-calculator',\n template: `\n <h2>Power Boost Calculator</h2>\n <div>Normal power: <input [(ngModel)]=\"power\"></div>\n <div>Boost factor: <input [(ngModel)]=\"factor\"></div>\n <p>\n Super Hero Power: {{power | exponentialStrength: factor}}\n </p>\n `\n})\nexport class PowerBoostCalculatorComponent {\n power = 5;\n factor = 1;\n}\n\n\n\n

The exponentialStrength pipe executes every time the user changes the \"normal power\" value or the \"boost factor\", as shown in Figure 3.

\n
\n \"Power\n
\n

Figure 3. Changing the amount and boost factor for the exponentialStrength pipe

\n

Angular detects each change and immediately runs the pipe.\nThis is fine for primitive input values.\nHowever, if you change something inside a composite object (such as the month of a date, an element of an array, or an object property), you need to understand how change detection works, and how to use an impure pipe.

\n

How change detection workslink

\n

Angular looks for changes to data-bound values in a change detection process that runs after every DOM event: every keystroke, mouse move, timer tick, and server response.\nThe following example, which doesn't use a pipe, demonstrates how Angular uses its default change detection strategy to monitor and update its display of every hero in the heroes array.\nThe example tabs show the following:

\n\n\n \nNew hero:\n <input type=\"text\" #box\n (keyup.enter)=\"addHero(box.value); box.value=''\"\n placeholder=\"hero name\">\n <button (click)=\"reset()\">Reset</button>\n <div *ngFor=\"let hero of heroes\">\n {{hero.name}}\n </div>\n\n\n \nexport class FlyingHeroesComponent {\n heroes: any[] = [];\n canFly = true;\n constructor() { this.reset(); }\n\n addHero(name: string) {\n name = name.trim();\n if (!name) { return; }\n const hero = {name, canFly: this.canFly};\n this.heroes.push(hero);\n }\n\n reset() { this.heroes = HEROES.slice(); }\n}\n\n\n\n

Angular updates the display every time the user adds a hero.\nIf the user clicks the Reset button, Angular replaces heroes with a new array of the original heroes and updates the display.\nIf you add the ability to remove or change a hero, Angular would detect those changes and update the display as well.

\n

However, executing a pipe to update the display with every change would slow down your app's performance.\nSo Angular uses a faster change-detection algorithm for executing a pipe, as described in the next section.

\n\n

Detecting pure changes to primitives and object referenceslink

\n

By default, pipes are defined as pure so that Angular executes the pipe only when it detects a pure change to the input value.\nA pure change is either a change to a primitive input value (such as String, Number, Boolean, or Symbol), or a changed object reference (such as Date, Array, Function, or Object).

\n\n

A pure pipe must use a pure function, which is one that processes inputs and returns values without side effects.\nIn other words, given the same input, a pure function should always return the same output.

\n

With a pure pipe, Angular ignores changes within composite objects, such as a newly added element of an existing array, because checking a primitive value or object reference is much faster than performing a deep check for differences within objects.\nAngular can quickly determine if it can skip executing the pipe and updating the view.

\n

However, a pure pipe with an array as input may not work the way you want.\nTo demonstrate this issue, change the previous example to filter the list of heroes to just those heroes who can fly.\nUse the FlyingHeroesPipe in the *ngFor repeater as shown in the following code.\nThe tabs for the example show the following:

\n\n\n \n<div *ngFor=\"let hero of (heroes | flyingHeroes)\">\n {{hero.name}}\n</div>\n\n\n \nimport { Pipe, PipeTransform } from '@angular/core';\n\nimport { Hero } from './heroes';\n\n@Pipe({ name: 'flyingHeroes' })\nexport class FlyingHeroesPipe implements PipeTransform {\n transform(allHeroes: Hero[]) {\n return allHeroes.filter(hero => hero.canFly);\n }\n}\n\n\n\n

The app now shows unexpected behavior: When the user adds flying heroes, none of them appear under \"Heroes who fly.\"\nThis happens because the code that adds a hero does so by pushing it onto the heroes array:

\n\nthis.heroes.push(hero);\n\n\n

The change detector ignores changes to elements of an array, so the pipe doesn't run.

\n

The reason Angular ignores the changed array element is that the reference to the array hasn't changed.\nSince the array is the same, Angular does not update the display.

\n

One way to get the behavior you want is to change the object reference itself.\nYou can replace the array with a new array containing the newly changed elements, and then input the new array to the pipe.\nIn the above example, you can create an array with the new hero appended, and assign that to heroes. Angular detects the change in the array reference and executes the pipe.

\n

To summarize, if you mutate the input array, the pure pipe doesn't execute.\nIf you replace the input array, the pipe executes and the display is updated, as shown in Figure 4.

\n
\n \"Flying\n
\n

Figure 4. The flyingHeroes pipe filtering the display to flying heroes

\n

The above example demonstrates changing a component's code to accommodate a pipe.

\n

To keep your component simpler and independent of HTML templates that use pipes, you can, as an alternative, use an impure pipe to detect changes within composite objects such as arrays, as described in the next section.

\n\n

Detecting impure changes within composite objectslink

\n

To execute a custom pipe after a change within a composite object, such as a change to an element of an array, you need to define your pipe as impure to detect impure changes.\nAngular executes an impure pipe every time it detects a change with every keystroke or mouse movement.

\n
\n

While an impure pipe can be useful, be careful using one. A long-running impure pipe could dramatically slow down your app.

\n
\n

Make a pipe impure by setting its pure flag to false:

\n\n@Pipe({\n name: 'flyingHeroesImpure',\n pure: false\n})\n\n\n

The following code shows the complete implementation of FlyingHeroesImpurePipe, which extends FlyingHeroesPipe to inherit its characteristics.\nThe example shows that you don't have to change anything else—the only difference is setting the pure flag as false in the pipe metadata.

\n\n \n@Pipe({\n name: 'flyingHeroesImpure',\n pure: false\n})\nexport class FlyingHeroesImpurePipe extends FlyingHeroesPipe {}\n\n\n \nimport { Pipe, PipeTransform } from '@angular/core';\n\nimport { Hero } from './heroes';\n\n@Pipe({ name: 'flyingHeroes' })\nexport class FlyingHeroesPipe implements PipeTransform {\n transform(allHeroes: Hero[]) {\n return allHeroes.filter(hero => hero.canFly);\n }\n}\n\n\n\n

FlyingHeroesImpurePipe is a good candidate for an impure pipe because the transform function is trivial and fast:

\n\nreturn allHeroes.filter(hero => hero.canFly);\n\n\n

You can derive a FlyingHeroesImpureComponent from FlyingHeroesComponent.\nAs shown in the code below, only the pipe in the template changes.

\n\n<div *ngFor=\"let hero of (heroes | flyingHeroesImpure)\">\n {{hero.name}}\n</div>\n\n\n
\n

To confirm that the display updates as the user adds heroes, see the .

\n
\n\n

Unwrapping data from an observablelink

\n

Observables let you pass messages between parts of your application.\nObservables are recommended for event handling, asynchronous programming, and handling multiple values.\nObservables can deliver single or multiple values of any type, either synchronously (as a function delivers a value to its caller) or asynchronously on a schedule.

\n
\n

For details and examples of observables, see the Observables Overview.

\n
\n

Use the built-in AsyncPipe to accept an observable as input and subscribe to the input automatically.\nWithout this pipe, your component code would have to subscribe to the observable to consume its values, extract the resolved values, expose them for binding, and unsubscribe when the observable is destroyed in order to prevent memory leaks. AsyncPipe is an impure pipe that saves boilerplate code in your component to maintain the subscription and keep delivering values from that observable as they arrive.

\n

The following code example binds an observable of message strings\n(message$) to a view with the async pipe.

\n\nimport { Component } from '@angular/core';\n\nimport { Observable, interval } from 'rxjs';\nimport { map, take } from 'rxjs/operators';\n\n@Component({\n selector: 'app-hero-message',\n template: `\n <h2>Async Hero Message and AsyncPipe</h2>\n <p>Message: {{ message$ | async }}</p>\n <button (click)=\"resend()\">Resend</button>`,\n})\nexport class HeroAsyncMessageComponent {\n message$: Observable<string>;\n\n private messages = [\n 'You are my hero!',\n 'You are the best hero!',\n 'Will you be my hero?'\n ];\n\n constructor() { this.resend(); }\n\n resend() {\n this.message$ = interval(500).pipe(\n map(i => this.messages[i]),\n take(this.messages.length)\n );\n }\n}\n\n\n\n

Caching HTTP requestslink

\n

To communicate with backend services using HTTP, the HttpClient service uses observables and offers the HttpClient.get() method to fetch data from a server.\nThe asynchronous method sends an HTTP request, and returns an observable that emits the requested data for the response.

\n

As shown in the previous section, you can use the impure AsyncPipe to accept an observable as input and subscribe to the input automatically.\nYou can also create an impure pipe to make and cache an HTTP request.

\n

Impure pipes are called whenever change detection runs for a component, which could be every few milliseconds for CheckAlways.\nTo avoid performance problems, call the server only when the requested URL changes, as shown in the following example, and use the pipe to cache the server response.\nThe tabs show the following:

\n\n\n \nimport { HttpClient } from '@angular/common/http';\nimport { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({\n name: 'fetch',\n pure: false\n})\nexport class FetchJsonPipe implements PipeTransform {\n private cachedData: any = null;\n private cachedUrl = '';\n\n constructor(private http: HttpClient) { }\n\n transform(url: string): any {\n if (url !== this.cachedUrl) {\n this.cachedData = null;\n this.cachedUrl = url;\n this.http.get(url).subscribe(result => this.cachedData = result);\n }\n\n return this.cachedData;\n }\n}\n\n\n\n \nimport { Component } from '@angular/core';\n\n@Component({\n selector: 'app-hero-list',\n template: `\n <h2>Heroes from JSON File</h2>\n\n <div *ngFor=\"let hero of ('assets/heroes.json' | fetch) \">\n {{hero.name}}\n </div>\n\n <p>Heroes as JSON:\n {{'assets/heroes.json' | fetch | json}}\n </p>`\n})\nexport class HeroListComponent { }\n\n\n\n\n

In the above example, a breakpoint on the pipe's request for data shows the following:

\n\n

The fetch and fetch-json pipes display the heroes as shown in Figure 5.

\n
\n \"Hero\n
\n

Figure 5. The fetch and fetch-json pipes displaying the heroes

\n
\n

The built-in JsonPipe provides a way to diagnose a mysteriously failing data binding or to inspect an object for future binding.

\n
\n

Pipes and precedencelink

\n

The pipe operator has a higher precedence than the ternary operator (?:), which means a ? b : c | x is parsed as a ? b : (c | x).\nThe pipe operator cannot be used without parentheses in the first and second operands of ?:.

\n

Due to precedence, if you want a pipe to apply to the result of a ternary, wrap the entire expression in parentheses; for example, (a ? b : c) | x.

\n\n<!-- use parentheses in the third operand so the pipe applies to the whole expression -->\n{{ (true ? 'true' : 'false') | uppercase }}\n\n\n\n \n
\n\n\n" }