| 
									
										
										
										
											2016-02-05 23:27:06 -08:00
										 |  |  | include ../_util-fns | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   Every application starts out with what seems like a simple task: get data, transform them, and show them to users. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Getting data could be as simple as creating a local variable or as complex as streaming data over a Websocket. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Once data arrive, we could push their raw `toString` values directly to screen. | 
					
						
							|  |  |  |   That rarely makes for a good user experience. | 
					
						
							|  |  |  |   Almost everyone prefers a simple birthday date | 
					
						
							|  |  |  |   (<span style="font-family:courier">April 15, 1988</span>) to the original raw string format | 
					
						
							|  |  |  |   ( <span style="font-family:courier">Fri Apr 15 1988 00:00:00 GMT-0700 (Pacific Daylight Time)</span> ). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   Clearly some values benefit from a bit of massage. We soon discover that we | 
					
						
							|  |  |  |   desire many of the same transformations repeatedly, both within and across many applications. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   We almost think of them as styles. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   In fact, we'd like to apply them in our HTML templates as we do styles. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   Welcome, Angular pipes, the simple display-value transformations that we can declare in our HTML! | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   [Live Example](/resources/live-examples/pipes/ts/plnkr.html). | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   ## Using Pipes | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   A pipe takes in data as input and transforms it to a desired output. | 
					
						
							|  |  |  |   We'll illustrate by transforming a component's birthday property into | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   a human-friendly date: | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | +makeExample('pipes/ts/app/hero-birthday1.component.ts', null, 'app/hero-birthday1.component.ts')(format='.') | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   Focus on the component's template. | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | +makeExample('pipes/ts/app/app.component.html', 'hero-birthday-template')(format=".") | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   Inside the interpolation expression we flow the component's `birthday` value through the | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   [pipe operator](./template-syntax.html#pipe) ( | ) to the [Date pipe](../api/common/DatePipe-class.html) | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   function on the right. All pipes work this way. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   ## Built-in pipes | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   Angular comes with a stock set of pipes such as | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   `DatePipe`, `UpperCasePipe`, `LowerCasePipe`, `CurrencyPipe`, and `PercentPipe`. | 
					
						
							|  |  |  |   They are all immediately available for use in any template. | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |     Learn more about these and many other built-in pipes in the  the [API Reference](../api/#!?apiFilter=pipe); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |     filter for entries that include the word "pipe". | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |     Angular 2 doesn't have a `FilterPipe` or an `OrderByPipe` for reasons explained in an [appendix below](#no-filter-pipe) | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   ## Parameterizing a Pipe | 
					
						
							|  |  |  |   A pipe may accept any number of optional parameters to fine-tune its output. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   We add parameters to a pipe by following the pipe name with a colon ( : ) and then the parameter value | 
					
						
							| 
									
										
										
										
											2015-10-23 09:31:51 -07:00
										 |  |  |   (e.g., `currency:'EUR'`). If our pipe accepts multiple parameters, we separate the values with colons (e.g. `slice:1:5`) | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   We'll modify our birthday template to give the date pipe a format parameter. | 
					
						
							|  |  |  |   After formatting the hero's April 15th birthday should display as **<span style="font-family:courier">04/15/88</span>**. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | +makeExample('pipes/ts/app/app.component.html', 'format-birthday')(format=".") | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   The parameter value can be any valid | 
					
						
							| 
									
										
										
										
											2016-02-12 20:24:42 +05:30
										 |  |  |   [template expression](./template-syntax.html#template-expressions) | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   such as a string literal or a component property. | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   In other words, we can control the format through a binding the same way we control the birthday value through a binding. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   Let's write a second component that *binds* the pipe's format parameter | 
					
						
							|  |  |  |   to the component's `format` property. Here's the template for that component: | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/hero-birthday2.component.ts', 'template', 'app/hero-birthday2.component.ts (template)')(format=".") | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   We also added a button to the template and bound its click event to the component's `toggleFormat` method. | 
					
						
							|  |  |  |   That method toggles the component's `format` property between a short form | 
					
						
							|  |  |  |   ('shortDate') and a longer form ('fullDate'). | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | +makeExample('pipes/ts/app/hero-birthday2.component.ts', 'class', 'app/hero-birthday2.component.ts (class)')(format='.') | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   As we click the button, the displayed date alternates between | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  |   "**<span style="font-family:courier">04/15/1988</span>**" and | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   "**<span style="font-family:courier">Friday, April 15, 1988</span>**". | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | figure.image-display | 
					
						
							|  |  |  |     img(src='/resources/images/devguide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle") | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | .l-sub-section | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-03-10 23:24:28 -08:00
										 |  |  |     Learn more about the `DatePipes` format options in the [API Docs](../api/common/DatePipe-class.html). | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   ## Chaining pipes | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   We can chain pipes together in potentially useful combinations. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   In the following example, we chain the birthday to the `DatePipe` and on to the `UpperCasePipe` | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   so we can display the birthday in uppercase. The following birthday displays as | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   **<span style="font-family:courier">APR 15, 1988</span>** | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | +makeExample('pipes/ts/app/app.component.html', 'chained-birthday')(format=".") | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   If we pass a parameter to a filter, we have to add parentheses | 
					
						
							|  |  |  |   to help the template compiler with the evaluation order. | 
					
						
							|  |  |  |   The following example displays | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   **<span style="font-family:courier">FRIDAY, APRIL 15, 1988</span>** | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | +makeExample('pipes/ts/app/app.component.html', 'chained-parameter-birthday')(format=".") | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   We can add parentheses to alter the evaluation order or | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   to provide extra clarity: | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/app.component.html', 'chained-parameter-birthday-parens')(format=".") | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   ## Custom Pipes | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  |   We can write our own custom pipes. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   Here's a custom pipe named `ExponentialStrengthPipe` that can boost a hero's powers: | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | +makeExample('pipes/ts/app/exponential-strength.pipe.ts', null, 'app/exponential-strength.pipe.ts')(format=".") | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-11-21 20:05:50 -06:00
										 |  |  |   This pipe definition reveals several key points | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   * A pipe is a class decorated with pipe metadata. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 11:52:41 -08:00
										 |  |  |   * The pipe class implements the `PipeTransform` interface's `transform` method that | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   accepts an input value and an optional array of parameters and returns the transformed value. | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   * There will be one item in the parameter array for each parameter passed to the pipe | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   * We tell Angular that this is a pipe by applying the | 
					
						
							|  |  |  |   `@Pipe` decorator which we import from the core Angular library. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   * The `@Pipe` decorator takes an object with a name property whose value is the | 
					
						
							| 
									
										
										
										
											2015-11-17 13:17:14 -05:00
										 |  |  |      pipe name that we'll use within a template expression. It must be a valid JavaScript identifier. | 
					
						
							| 
									
										
										
										
											2016-01-15 14:30:00 -06:00
										 |  |  |      Our pipe's name is `exponentialStrength`. | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 11:52:41 -08:00
										 |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     ### The *PipeTransform* Interface | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |     The `transform` method is essential to a pipe. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |     The `PipeTransform` *interface* defines that method and guides both tooling and the compiler. | 
					
						
							|  |  |  |     It is technically optional; Angular looks for and executes the `transform` method regardless. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 11:52:41 -08:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   Now we need a component to demonstrate our pipe. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | +makeExample('pipes/ts/app/power-booster.component.ts',null,'app/power-booster.component.ts')(format='.') | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | figure.image-display | 
					
						
							|  |  |  |     img(src='/resources/images/devguide/pipes/power-booster.png' alt="Power Booster") | 
					
						
							| 
									
										
										
										
											2015-10-17 10:01:41 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-23 09:31:51 -07:00
										 |  |  |   Two things to note: | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   1. We use our custom pipe the same way we use the built-in pipes. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   1. We must list our pipe in the `pipes` array of the `@Component` decorator. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | .callout.is-helpful | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   header Remember the pipes array! | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |   :marked | 
					
						
							|  |  |  |     Angular reports an error if we neglect to list our custom pipe. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |     We didn't list the `DatePipe` in our previous example because all | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |     Angular built-in pipes are pre-registered. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |     Custom pipes must be registered manually. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   If we try the [live code](/resources/live-examples/pipes/ts/plnkr.html) example, | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   we can probe its behavior by changing the value and the optional exponent in the template. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   ## Power Boost Calculator (extra-credit) | 
					
						
							|  |  |  |   It's not much fun updating the template to test our custom pipe. | 
					
						
							|  |  |  |   We could upgrade the example to a "Power Boost Calculator" that combines | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   our pipe and two-way data binding with `ngModel`. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | +makeExample('pipes/ts/app/power-boost-calculator.component.ts', null, '/app/power-boost-calculator.component.ts')(format='.') | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | figure.image-display | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |     img(src='/resources/images/devguide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator") | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-17 10:01:41 -07:00
										 |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | a(id="change-detection") | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Pipes and Change Detection | 
					
						
							|  |  |  |   Angular looks for changes to data-bound values through a *change detection* process that runs after every JavaScript event: | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   every keystroke, mouse move, timer tick, and server response. It could be expensive. | 
					
						
							|  |  |  |   Angular strives to lower the cost whenever possible and appropriate. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Angular picks a simpler, faster change detection algorithm when we use a pipe. Let's see how. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ### No pipe | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   The component in our next example uses the default, aggressive change detection strategy to monitor and update | 
					
						
							|  |  |  |   its display of every hero in the `heroes` array. Here's the template: | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/flying-heroes.component.html', 'template-1', 'app/flying-heroes.component.html (v1)')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The companion component class provides heroes, pushes new heroes into the array, and can reset the array. | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/flying-heroes.component.ts', 'v1', 'app/flying-heroes.component.ts (v1)')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   We can add a new hero and Angular updates the display when we do. | 
					
						
							|  |  |  |   The `reset` button replaces `heroes` with a new array of the original heroes and Angular updates the display when we do. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   If we added the ability to remove or change a hero, Angular would detect those changes too and update the display again. | 
					
						
							|  |  |  |   add or remove heroes. It updates the display when we modify a hero. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   ### Flying Heroes pipe | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Let's add a `FlyingHeroesPipe` to the `*ngFor` repeater that filters the list of heroes to just those heroes who can fly. | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/flying-heroes.component.html', 'template-flying-heroes', 'app/flying-heroes.component.html (flyers)')(format='.') | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Here's the `FlyingHeroesPipe` implementation which follows the pattern for custom pipes we saw earlier. | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/flying-heroes.pipe.ts', 'pure', 'app/flying-heroes.pipe.ts')(format='.') | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | :marked | 
					
						
							|  |  |  |   When we run the sample now we see odd behavior (try it in the [live example](/resources/live-examples/pipes/ts/plnkr.html)). | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   Every hero we add is a flying hero but none of them are displayed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Although we're not getting the behavior we want, Angular isn't broken. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   It's just using a different change detection algorithm — one that ignores changes to the list or any of its items. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Look at how we're adding a new hero: | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/flying-heroes.component.ts', 'push')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   We're pushing the new hero into the `heroes` array.  The object reference to the array hasn't changed. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   It's the same array. That's all Angular cares about. From its perspective, *same array, no change, no display update*. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   We can fix that. Let's use `concat` to create a new array with the new hero appended and assign that to `heroes`. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   This time Angular detects that the array object reference has changed. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   It executes the pipe and updates the display with the new array which includes the new flying hero. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   *If we **mutate** the array, no pipe and no display update; | 
					
						
							|  |  |  |   if we **replace** the array, the pipe executes and the display updates*. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   The *Flying Heroes* in the [live example](/resources/live-examples/pipes/ts/plnkr.html) extends the | 
					
						
							|  |  |  |   code with checkbox switches and additional displays to help us experience these effects. | 
					
						
							|  |  |  | figure.image-display | 
					
						
							|  |  |  |     img(src='/resources/images/devguide/pipes/flying-heroes-anim.gif' alt="Flying Heroes") | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | :marked | 
					
						
							|  |  |  |   Replacing the array is an efficient way to signal to Angular that it should update the display. | 
					
						
							|  |  |  |   When do we replace the array? When the data change. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   That's an easy rule to follow in *this toy* example | 
					
						
							|  |  |  |   where the only way to change the data is by adding a new hero. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   More often we don't know when the data have changed, | 
					
						
							|  |  |  |   especially in applications that mutate data in many ways, | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   perhaps in application locations far away. | 
					
						
							|  |  |  |   A component is such an application usually can't know about those changes. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Moreover, it's unwise to distort our component design to accommodate a pipe. | 
					
						
							|  |  |  |   We strive as much as possible to keep the component class independent of the HTML. | 
					
						
							|  |  |  |   The component should be unaware of pipes. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Perhaps we should consider a different kind of pipe for filtering flying heroes, an *impure pipe*. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Pure and Impure Pipes | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   There are two categories of pipes: **pure** and **impure**. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Pipes are pure by default.  Every pipe we've seen so far has been pure. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   We make a pipe impure by setting its pure flag to false. We could make the `FlyingHeroesPipe` | 
					
						
							|  |  |  |   impure with a flip of the switch: | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | +makeExample('pipes/ts/app/flying-heroes.pipe.ts', 'pipe-decorator')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Before we do that, let's understand the difference between *pure* and *impure*, starting with a *pure* pipe. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   ### Pure pipes | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Angular executes a *pure pipe* only when it detects a *pure change* to the input value. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   A *pure change* is *either* a change to a primitive input value (`String`, `Number`, `Boolean`, `Symbol`) | 
					
						
							|  |  |  |   *or* a changed object reference (`Date`, `Array`, `Function`, `Object`). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Angular ignores changes *within* the object itself. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   It won't call a pure pipe if we change the input month, add to the input array, or update an input object property. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   This may seem restrictive but is is also fast. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   An object reference check is fast ... much faster than a deep check for differences. | 
					
						
							|  |  |  |   ... so Angular can quickly determine if it can skip both the pipe execution and a screen update. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   For this reason, we prefer a pure pipe if we can live with the change detection strategy. | 
					
						
							|  |  |  |   When we can't, we *may* turn to the impure pipe. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |     Or we might not use a pipe at all. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |     It may be better to pursue the pipe's purpose with a property of the component, | 
					
						
							|  |  |  |     a point we take up later. | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Impure pipes | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   Angular executes an *impure pipe*  during *every* component change detection cycle. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   An impure pipe will be called a lot, as often as every keystroke or mouse-move. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   With that concern in mind, we must implement an impure pipe with great care. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   An expensive, long-running pipe could destroy the user experience. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   <a id="impure-flying-heroes"></a> | 
					
						
							|  |  |  |   ### An impure *FlyingHeroesPipe* | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   A flip of the switch turns our `FlyingHeroesPipe` into a `FlyingHeroesImpurePipe`. | 
					
						
							|  |  |  |   Here's the complete implementation: | 
					
						
							|  |  |  | +makeTabs( | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   'pipes/ts/app/flying-heroes.pipe.ts, pipes/ts/app/flying-heroes.pipe.ts', | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   'impure, pure', | 
					
						
							|  |  |  |   'FlyingHeroesImpurePipe, FlyingHeroesPipe')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We inherit from `FlyingHeroesPipe` to prove the point that nothing changed internally. | 
					
						
							|  |  |  |   The only difference is the `pure` flag in the pipe metadata. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   This is a good candidate for an impure pipe because the `transform` function is trivial and fast. | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/flying-heroes.pipe.ts','filter')(format='.') | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   We can derive a `FlyingHeroesImpureComponent` that we derive from the `FlyingHeroesComponent`. | 
					
						
							| 
									
										
										
										
											2016-03-26 12:18:13 -04:00
										 |  |  | +makeExample('pipes/ts/app/flying-heroes.component.ts','impure-component','app/flying-heroes.component.ts (FlyingHeroesImpureComponent)')(format='.') | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   The only substantive change is the pipe. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   We can confirm in the [live example](/resources/live-examples/pipes/ts/plnkr.html) | 
					
						
							|  |  |  |   that the *flying heroes* display updates as we enter new heroes even when we mutate the `heroes` array. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-01 12:15:14 +01:00
										 |  |  |   <a id="async-pipe"></a> | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   ### The impure *AsyncPipe* | 
					
						
							|  |  |  |   The Angular `AsyncPipe` is an interesting example of an impure pipe. | 
					
						
							|  |  |  |   The `AsyncPipe` accepts a `Promise` or `Observable` as input | 
					
						
							|  |  |  |   and subscribes to the input automatically, eventually returning the emitted value(s). | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   It is also stateful. | 
					
						
							|  |  |  |   The pipe maintains a subscription to the input `Observable` and | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   keeps delivering values from that `Observable` as they arrive. | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   In this next example, we bind an `Observable` of message strings (`messages$`) to a view with the `async` pipe. | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | +makeExample('pipes/ts/app/hero-async-message.component.ts', null, 'app/hero-async-message.component.ts') | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   The Async pipe saves boilerplate in the component code. | 
					
						
							|  |  |  |   The component doesn't have to subscribe to the async data source, | 
					
						
							| 
									
										
										
										
											2015-10-23 09:31:51 -07:00
										 |  |  |   it doesn't extract the resolved values and expose them for binding, | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   and the component doesn't have to unsubscribe when it is destroyed | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  |   (a potent source of memory leaks). | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   ### An impure caching pipe | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Let's write one more impure pipe, a pipe that makes an http request to the server. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Normally, that's a horrible idea. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   It's probably a horrible idea no matter what we do. | 
					
						
							|  |  |  |   We're forging ahead anyway to make a point. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Remember that impure pipes are called every few microseconds. | 
					
						
							|  |  |  |   If we're not careful, this pipe will punish the server with requests. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   We are careful. Our pipe only makes a server call if the request URL has changed. | 
					
						
							|  |  |  |   It caches the request URL and waits for a result which it also caches when it arrives. | 
					
						
							|  |  |  |   The pipe returns the cached result (which is null while a request is in flight) | 
					
						
							|  |  |  |   after every Angular call and only contacts the server as necessary. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Here's the code, which uses the [Angular http](server-communication.html) facility | 
					
						
							|  |  |  |   to retrieve a `heroes.json` file: | 
					
						
							| 
									
										
										
										
											2015-10-19 09:56:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | +makeExample('pipes/ts/app/fetch-json.pipe.ts', null, 'app/fetch-json.pipe.ts') | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Then we demonstrate it in a harness component whose template defines two bindings to this pipe. | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | +makeExample('pipes/ts/app/hero-list.component.ts', 'template', 'app/hero-list.component.ts (template)') | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   Despite the two bindings and what we know to be frequent pipe calls, | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   the nework tab in the browser developer tools confirms that there is only one request for the file. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  |   The component renders like this: | 
					
						
							| 
									
										
										
										
											2015-11-02 00:28:38 -08:00
										 |  |  | figure.image-display | 
					
						
							|  |  |  |     img(src='/resources/images/devguide/pipes/hero-list.png' alt="Hero List") | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   ### *JsonPipe* | 
					
						
							|  |  |  |   The second binding involving the `FetchPipe` uses more pipe chaining. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   We take the same fetched results displayed in the first binding | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   and display them again, this time in JSON format by chaining through to the built-in `JsonPipe`. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | .callout.is-helpful | 
					
						
							|  |  |  |   header Debugging with the json pipe | 
					
						
							|  |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-03-16 21:42:55 -07:00
										 |  |  |     The [JsonPipe](../api/common/JsonPipe-class.html) | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |     provides an easy way to diagnosis a mysteriously failing data binding or | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |     inspect an object for future binding. | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | :marked | 
					
						
							|  |  |  |   Here's the complete component implementation: | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/hero-list.component.ts', null, 'app/hero-list.component.ts') | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | a(id="pure-pipe-pure-fn") | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Pure pipes vs. pure functions | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   When developers first hear of *pure pipes* many of them think these pipes must be *pure functions*. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Pure functions process inputs and return values without detectable side-effects. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Given the same input they should always return the same output. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Pure pipes _are_ typically implemented with pure function. | 
					
						
							|  |  |  |   The pipes we saw earlier in this chapter were implemented with pure functions. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   The built-in `DatePipe` is a pure pipe with a pure function implementation. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   So is our `ExponentialStrengthPipe`. | 
					
						
							|  |  |  |   So is our `FlyingHeroesPipe`. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   But there is no necessary connection between a pure pipe and a pure function. | 
					
						
							|  |  |  |   A few steps back we reviewed the `FlyingHeroesImpurePipe` — *an impure pipe with a pure function*. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   We can also write *a pure pipe with an impure function* such as the | 
					
						
							|  |  |  |   `RandomizerPipe` (also in the [live example](/resources/live-examples/pipes/ts/plnkr.html)) | 
					
						
							|  |  |  |   that ignores its input value and outputs a random number. Clearly an impure function! | 
					
						
							|  |  |  |   Yet it's perfectly well behaved as a pure pipe. | 
					
						
							|  |  |  | +makeExample('pipes/ts/app/random-pipe.component.ts', 'pipe','app/random-pipe.component.ts (pipe)')(format='.') | 
					
						
							| 
									
										
										
										
											2015-12-12 22:01:46 -08:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   When the input changes, it outputs a new value albeit never the same value for the same input. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Remember *purity in a pipe has nothing to do with pure functions!* | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   *Pipe purity* is more about the purity of the input values than of the pipe itself. | 
					
						
							| 
									
										
										
										
											2015-10-23 09:31:51 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-23 09:31:51 -07:00
										 |  |  |   ## Next Steps | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-23 09:31:51 -07:00
										 |  |  |   Pipes are a great way to encapsulate and share common display-value | 
					
						
							|  |  |  |   transformations. We use them like styles, dropping them | 
					
						
							|  |  |  |   into our templates expressions to enrich the appeal and usability | 
					
						
							|  |  |  |   of our views. | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Explore Angular's inventory of built-in pipes in the [API Reference](../api/#!?apiFilter=pipe). | 
					
						
							| 
									
										
										
										
											2015-11-17 13:17:14 -05:00
										 |  |  |   Try writing a custom pipe and perhaps contributing it to the community. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | a(id="no-filter-pipe") | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## No *FilterPipe* or *OrderByPipe* | 
					
						
							|  |  |  |   Angular does not ship with pipes for filtering or sorting lists. | 
					
						
							|  |  |  |   Developers familiar with Angular 1 know these as `filter` and `orderBy`. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   There are no equivalents in Angular 2. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   This is not an oversight. Angular 2 is unlikely to offer such pipes because | 
					
						
							|  |  |  |   (a) they perform poorly and (b) they prevent aggressive minification. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Both *filter* and *orderBy* require parameters that reference object properties. | 
					
						
							|  |  |  |   We learned earlier that such pipes must be  [*impure*](#pure-and-impure-pipes) and that | 
					
						
							|  |  |  |   Angular calls impure pipes in almost every change detection cycle. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Filtering and especially sorting are expensive operations. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   The user experience can degrade severely for even moderate sized lists when Angular calls these pipe methods many times per second. | 
					
						
							|  |  |  |   The `filter` and `orderBy` have often been abused in Angular 1 apps, leading to complaints that Angular itself is slow. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   That charge is fair in the indirect sense that Angular 1 prepared this performance trap | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   by offering `filter` and `orderBy` in the first place. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   The minification hazard is also compelling if less obvious. Imagine a sorting pipe applied to a list of heroes. | 
					
						
							|  |  |  |   We might sort the list by hero `name` and `planet` origin properties something like this: | 
					
						
							|  |  |  | code-example(format="." language="html") | 
					
						
							|  |  |  |   <!-- NOT REAL CODE! --> | 
					
						
							|  |  |  |   <div *ngFor="#hero of heroes | orderBy:'name,planet'"></div> | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We identify the sort fields by text strings, expecting the pipe to reference a property value by indexing | 
					
						
							|  |  |  |   (e.g., `hero['name']`). | 
					
						
							|  |  |  |   Unfortunately, aggressive minification *munges* the `Hero` property names so that `Hero.name` and `Hero.planet` | 
					
						
							|  |  |  |   becomes something like `Hero.a` and `Hero.b`. Clearly `hero['name']` is not going to work. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   Some of us may not care to minify this aggressively. That's *our* choice. | 
					
						
							|  |  |  |   But the Angular product should not prevent someone else from minifying aggressively. | 
					
						
							|  |  |  |   Therefore, the Angular team decided that everything shipped in Angular will minify safely. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   The Angular team and many experienced Angular developers strongly recommend that you move | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   filtering and sorting logic into the component itself. | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   The component can expose a `filteredHeroes` or `sortedHeroes` property and take control | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  |   over when and how often to execute the supporting logic. | 
					
						
							|  |  |  |   Any capabilities that you would have put in a pipe and shared across the app can be | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   written in a filtering/sorting service and injected into the component. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   If these performance and minification considerations do not apply to you, you can always create your own such pipes | 
					
						
							| 
									
										
										
										
											2016-01-13 15:00:43 -07:00
										 |  |  |   (along the lines of the [FlyingHeroesPipe](#impure-flying-heroes)) or find them in the community. | 
					
						
							| 
									
										
										
										
											2016-04-06 21:15:07 +03:00
										 |  |  | 
 |