parent
							
								
									8fe40026c1
								
							
						
					
					
						commit
						4ff636d24d
					
				| @ -102,7 +102,7 @@ describe('Pipes', () => { | |||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   it('should show an async hero message', async () => { |   it('should show an async hero message', async () => { | ||||||
|     expect(await element.all(by.tagName('app-hero-message')).get(0).getText()).toContain('hero'); |     expect(await element.all(by.tagName('app-hero-async-message')).get(0).getText()).toContain('hero'); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -1,16 +1,16 @@ | |||||||
| <a id="toc"></a> | <a id="toc"></a> | ||||||
| <h1>Pipes</h1> | <h1>Pipes</h1> | ||||||
| <a href="#happy-birthday1">Happy Birthday v1</a><br> | <a href="#happy-birthday1">Happy Birthday v1</a> | ||||||
| <a href="#birthday-date-pipe">Birthday DatePipe</a><br> | <a href="#birthday-date-pipe">Birthday DatePipe</a> | ||||||
| <a href="#happy-birthday2">Happy Birthday v2</a><br> | <a href="#happy-birthday2">Happy Birthday v2</a> | ||||||
| <a href="#birthday-pipe-chaining">Birthday Pipe Chaining</a><br> | <a href="#birthday-pipe-chaining">Birthday Pipe Chaining</a> | ||||||
| <a href="#power-booster">Power Booster custom pipe</a><br> | <a href="#power-booster">Power Booster custom pipe</a> | ||||||
| <a href="#power-boost-calc">Power Boost Calculator custom pipe with params</a><br> | <a href="#power-boost-calc">Power Boost Calculator custom pipe with params</a> | ||||||
| <a href="#flying-heroes">Flying Heroes filter pipe (pure)</a><br> | <a href="#flying-heroes">Flying Heroes filter pipe (pure)</a> | ||||||
| <a href="#flying-heroes-impure">Flying Heroes filter pipe (impure)</a><br> | <a href="#flying-heroes-impure">Flying Heroes filter pipe (impure)</a> | ||||||
| <a href="#hero-message">Async Hero Message and AsyncPipe</a><br> | <a href="#hero-message">Async Hero Message and AsyncPipe</a> | ||||||
| <a href="#hero-list">Hero List with caching FetchJsonPipe</a><br> | <a href="#hero-list">Hero List with caching FetchJsonPipe</a> | ||||||
| <a href="#pipe-precedence">Pipes and Precedence</a><br> | <a href="#pipe-precedence">Pipes and Precedence</a> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -73,7 +73,7 @@ | |||||||
| <hr> | <hr> | ||||||
| <a id="hero-message"></a> | <a id="hero-message"></a> | ||||||
| <!-- async examples at the top so can see them in action --> | <!-- async examples at the top so can see them in action --> | ||||||
| <app-hero-message></app-hero-message> | <app-hero-async-message></app-hero-async-message> | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| <a id="hero-list"></a> | <a id="hero-list"></a> | ||||||
|  | |||||||
| @ -3,7 +3,8 @@ import { Component } from '@angular/core'; | |||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-root', |   selector: 'app-root', | ||||||
|   templateUrl: './app.component.html' |   templateUrl: './app.component.html', | ||||||
|  |   styles: ['a[href] {display: block; padding: 10px 0;}', 'a:hover {text-decoration: none;}', 'h2 {margin: 0;}'] | ||||||
| }) | }) | ||||||
| export class AppComponent { | export class AppComponent { | ||||||
|   birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
 |   birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
 | ||||||
|  | |||||||
| @ -1,19 +1,24 @@ | |||||||
| <!-- #docplaster--> | <!-- #docplaster--> | ||||||
| <!-- #docregion --> | <!-- #docregion --> | ||||||
| <h2>{{title}}</h2> | <h2>{{title}}</h2> | ||||||
| <p> | 
 | ||||||
| New hero: | <label for="hero-name">New hero: </label> | ||||||
|   <input type="text" #box | <input type="text" | ||||||
|  |        id="hero-name" | ||||||
|  |        #box | ||||||
|        (keyup.enter)="addHero(box.value); box.value=''" |        (keyup.enter)="addHero(box.value); box.value=''" | ||||||
|        placeholder="hero name"> |        placeholder="hero name"> | ||||||
|   <input id="can-fly" type="checkbox" [(ngModel)]="canFly"> can fly | <div> | ||||||
| </p> |   <input id="can-fly" type="checkbox" [(ngModel)]="canFly"> | ||||||
| <p> |   <label for="can-fly">can fly</label> | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <div> | ||||||
|   <input id="mutate" type="checkbox" [(ngModel)]="mutate">Mutate array |   <input id="mutate" type="checkbox" [(ngModel)]="mutate">Mutate array | ||||||
|   <button (click)="reset()">Reset</button> |   <button (click)="reset()">Reset</button> | ||||||
| </p> | </div> | ||||||
| 
 | 
 | ||||||
| <h4>Heroes who fly (piped)</h4> | <h3>Heroes who fly (piped)</h3> | ||||||
| <div id="flyers"> | <div id="flyers"> | ||||||
| <!-- #docregion template-flying-heroes --> | <!-- #docregion template-flying-heroes --> | ||||||
|   <div *ngFor="let hero of (heroes | flyingHeroesImpure)"> |   <div *ngFor="let hero of (heroes | flyingHeroesImpure)"> | ||||||
| @ -22,7 +27,7 @@ New hero: | |||||||
| <!-- #enddocregion template-flying-heroes --> | <!-- #enddocregion template-flying-heroes --> | ||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
| <h4>All Heroes (no pipe)</h4> | <h3>All Heroes (no pipe)</h3> | ||||||
| <div id="all"> | <div id="all"> | ||||||
|   <div *ngFor="let hero of heroes"> |   <div *ngFor="let hero of heroes"> | ||||||
|     {{hero.name}} |     {{hero.name}} | ||||||
|  | |||||||
| @ -1,23 +1,27 @@ | |||||||
| <!-- #docplaster--> | <!-- #docplaster--> | ||||||
| <!-- #docregion --> | <!-- #docregion --> | ||||||
| <h2>{{title}}</h2> | <h2>{{title}}</h2> | ||||||
| <p> | <p>Create a new hero and press enter to add it to the list. </p> | ||||||
| <!-- #docregion template-1 --> | <!-- #docregion template-1 --> | ||||||
| New hero: | <label for="hero-name">New hero name: </label> | ||||||
| <input type="text" #box | <input type="text" #box | ||||||
|  |        id="hero-name" | ||||||
|        (keyup.enter)="addHero(box.value); box.value=''" |        (keyup.enter)="addHero(box.value); box.value=''" | ||||||
|        placeholder="hero name"> |        placeholder="hero name"> | ||||||
| <!-- #enddocregion template-1 --> | <!-- #enddocregion template-1 --> | ||||||
|   <input id="can-fly" type="checkbox" [(ngModel)]="canFly"> can fly | <div> | ||||||
| </p> |   <input id="can-fly" type="checkbox" [(ngModel)]="canFly"> | ||||||
| <p> |   <label for="can-fly">Hero can fly</label> | ||||||
|   <input id="mutate" type="checkbox" [(ngModel)]="mutate">Mutate array | </div> | ||||||
|  | <div> | ||||||
|  | <input id="mutate" type="checkbox" [(ngModel)]="mutate"> | ||||||
|  | <label for="mutate">Mutate array</label> | ||||||
| <!-- #docregion template-1 --> | <!-- #docregion template-1 --> | ||||||
|   <button (click)="reset()">Reset</button> | <button (click)="reset()">Reset list of heroes</button> | ||||||
| <!-- #enddocregion template-1 --> | <!-- #enddocregion template-1 --> | ||||||
| </p> | </div> | ||||||
| 
 | 
 | ||||||
| <h4>Heroes who fly (piped)</h4> | <h3>Heroes who fly (piped)</h3> | ||||||
| <div id="flyers"> | <div id="flyers"> | ||||||
| <!-- #docregion template-flying-heroes --> | <!-- #docregion template-flying-heroes --> | ||||||
|   <div *ngFor="let hero of (heroes | flyingHeroes)"> |   <div *ngFor="let hero of (heroes | flyingHeroes)"> | ||||||
| @ -26,7 +30,7 @@ New hero: | |||||||
| <!-- #enddocregion template-flying-heroes --> | <!-- #enddocregion template-flying-heroes --> | ||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
| <h4>All Heroes (no pipe)</h4> | <h3>All Heroes (no pipe)</h3> | ||||||
| <div id="all"> | <div id="all"> | ||||||
| <!-- #docregion template-1 --> | <!-- #docregion template-1 --> | ||||||
|   <div *ngFor="let hero of heroes"> |   <div *ngFor="let hero of heroes"> | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ import { HEROES } from './heroes'; | |||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-flying-heroes', |   selector: 'app-flying-heroes', | ||||||
|   templateUrl: './flying-heroes.component.html', |   templateUrl: './flying-heroes.component.html', | ||||||
|   styles: ['#flyers, #all {font-style: italic}'] |   styles: ['#flyers, #all {font-style: italic}', 'button {display: block}', 'input {margin: .25rem .25rem .5rem 0;}'] | ||||||
| }) | }) | ||||||
| // #docregion v1
 | // #docregion v1
 | ||||||
| export class FlyingHeroesComponent { | export class FlyingHeroesComponent { | ||||||
| @ -48,7 +48,7 @@ export class FlyingHeroesComponent { | |||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-flying-heroes-impure', |   selector: 'app-flying-heroes-impure', | ||||||
|   templateUrl: './flying-heroes-impure.component.html', |   templateUrl: './flying-heroes-impure.component.html', | ||||||
|   styles: ['.flyers, .all {font-style: italic}'], |   styles: ['#flyers, #all {font-style: italic}', 'button {display: block}', 'input {margin: .25rem .25rem .5rem 0;}'], | ||||||
| }) | }) | ||||||
| export class FlyingHeroesImpureComponent extends FlyingHeroesComponent { | export class FlyingHeroesImpureComponent extends FlyingHeroesComponent { | ||||||
|   title = 'Flying Heroes (impure pipe)'; |   title = 'Flying Heroes (impure pipe)'; | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ import { Observable, interval } from 'rxjs'; | |||||||
| import { map, take } from 'rxjs/operators'; | import { map, take } from 'rxjs/operators'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-hero-message', |   selector: 'app-hero-async-message', | ||||||
|   template: ` |   template: ` | ||||||
|     <h2>Async Hero Message and AsyncPipe</h2> |     <h2>Async Hero Message and AsyncPipe</h2> | ||||||
|     <p>Message: {{ message$ | async }}</p> |     <p>Message: {{ message$ | async }}</p> | ||||||
|  | |||||||
| @ -5,12 +5,15 @@ import { Component } from '@angular/core'; | |||||||
|   selector: 'app-power-boost-calculator', |   selector: 'app-power-boost-calculator', | ||||||
|   template: ` |   template: ` | ||||||
|     <h2>Power Boost Calculator</h2> |     <h2>Power Boost Calculator</h2> | ||||||
|     <div>Normal power: <input [(ngModel)]="power"></div> |     <label for="power-input">Normal power: </label> | ||||||
|     <div>Boost factor: <input [(ngModel)]="factor"></div> |     <input id="power-input" type="text" [(ngModel)]="power"> | ||||||
|  |     <label for="boost-input">Boost factor: </label> | ||||||
|  |     <input id="boost-input" type="text" [(ngModel)]="factor"> | ||||||
|     <p> |     <p> | ||||||
|       Super Hero Power: {{power | exponentialStrength: factor}} |       Super Hero Power: {{power | exponentialStrength: factor}} | ||||||
|     </p> |     </p> | ||||||
|   ` |   `,
 | ||||||
|  |   styles: ['input {margin: .5rem 0;}'] | ||||||
| }) | }) | ||||||
| export class PowerBoostCalculatorComponent { | export class PowerBoostCalculatorComponent { | ||||||
|   power = 5; |   power = 5; | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
| <h2>{{title}}</h2> | <h2>{{title}}</h2> | ||||||
| 
 | 
 | ||||||
| <p>Basic uppercase pipe (no precedence considerations necessary): {{ 'text' | uppercase }}</p> | <p>Basic uppercase pipe (no precedence considerations necessary): {{ 'text' | uppercase }}</p> | ||||||
| <p>The following shows that a pipe has higher precedence than a ternary operator. If the pipe precedence were lower than the ternary operator precedence, the output would be 'TRUE'. Instead it is: {{ true ? 'true' : 'false' | uppercase }}</p> | <p>The following shows that a pipe has higher precedence than a ternary operator. If the pipe precedence were lower than the ternary operator precedence, the output would be in uppercase as in 'TRUE'. Instead "true" is lowercase: {{ true ? 'true' : 'false' | uppercase }}</p> | ||||||
| <p>The following shows how parentheses help Angular evaluate the whole statement: | <p>The following shows how parentheses help Angular evaluate the whole statement: | ||||||
| <!-- #docregion precedence --> | <!-- #docregion precedence --> | ||||||
| <!-- use parentheses in the third operand so the pipe applies to the whole expression --> | <!-- use parentheses in the third operand so the pipe applies to the whole expression --> | ||||||
|  | |||||||
| @ -2,8 +2,7 @@ import { Component } from '@angular/core'; | |||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-precedence', |   selector: 'app-precedence', | ||||||
|   templateUrl: './precedence.component.html', |   templateUrl: './precedence.component.html' | ||||||
|   styles: [] |  | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| export class PrecedenceComponent { | export class PrecedenceComponent { | ||||||
|  | |||||||
| @ -100,13 +100,7 @@ The tabs in the following example demonstrates toggling between two different fo | |||||||
|   </code-pane> |   </code-pane> | ||||||
| </code-tabs> | </code-tabs> | ||||||
| 
 | 
 | ||||||
| Clicking the **Toggle Format** button alternates the date format between **04/15/1988** and **Friday, April 15, 1988** as shown in Figure 1. | Clicking the **Toggle Format** button alternates the date format between **04/15/1988** and **Friday, April 15, 1988**. | ||||||
| 
 |  | ||||||
| <div class="lightbox"> |  | ||||||
|   <img src='generated/images/guide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle"> |  | ||||||
| </div> |  | ||||||
| 
 |  | ||||||
| **Figure 1.** Clicking the button toggles the date format |  | ||||||
| 
 | 
 | ||||||
| <div class="alert is-helpful"> | <div class="alert is-helpful"> | ||||||
| 
 | 
 | ||||||
| @ -176,7 +170,6 @@ The following code example shows two component definitions: | |||||||
| It defines an argument to the `transform` method (`exponent`) for a parameter passed to the pipe. | It defines an argument to the `transform` method (`exponent`) for a parameter passed to the pipe. | ||||||
| 
 | 
 | ||||||
| * The `power-booster.component.ts` component demonstrates how to use the pipe, specifying a value (`2`) and the exponent parameter (`10`). | * The `power-booster.component.ts` component demonstrates how to use the pipe, specifying a value (`2`) and the exponent parameter (`10`). | ||||||
| Figure 2 shows the output. |  | ||||||
| 
 | 
 | ||||||
| <code-tabs> | <code-tabs> | ||||||
|   <code-pane |   <code-pane | ||||||
| @ -189,11 +182,15 @@ Figure 2 shows the output. | |||||||
|   </code-pane> |   </code-pane> | ||||||
| </code-tabs> | </code-tabs> | ||||||
| 
 | 
 | ||||||
| <div class="lightbox"> | The browser displays the following: | ||||||
|   <img src='generated/images/guide/pipes/power-booster.png' alt="Power Booster"> |  | ||||||
| </div> |  | ||||||
| 
 | 
 | ||||||
| **Figure 2.** Output from the `exponentialStrength` pipe | <code-example language="none"> | ||||||
|  | 
 | ||||||
|  | Power Booster | ||||||
|  | 
 | ||||||
|  | Superpower boost: 1024 | ||||||
|  | 
 | ||||||
|  | </code-example> | ||||||
| 
 | 
 | ||||||
| <div class="alert is-helpful"> | <div class="alert is-helpful"> | ||||||
| 
 | 
 | ||||||
| @ -214,13 +211,7 @@ For example, you could change the previous custom pipe example to use two-way da | |||||||
| 
 | 
 | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| The `exponentialStrength` pipe executes every time the user changes the "normal power" value or the "boost factor", as shown in Figure 3. | The `exponentialStrength` pipe executes every time the user changes the "normal power" value or the "boost factor". | ||||||
| 
 |  | ||||||
| <div class="lightbox"> |  | ||||||
|   <img src='generated/images/guide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator"> |  | ||||||
| </div> |  | ||||||
| 
 |  | ||||||
| **Figure 3.** Changing the amount and boost factor for the `exponentialStrength` pipe |  | ||||||
| 
 | 
 | ||||||
| Angular detects each change and immediately runs the pipe. | Angular detects each change and immediately runs the pipe. | ||||||
| This is fine for primitive input values. | This is fine for primitive input values. | ||||||
| @ -306,17 +297,11 @@ You can replace the array with a new array containing the newly changed elements | |||||||
| In 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. | In 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. | ||||||
| 
 | 
 | ||||||
| To summarize, if you mutate the input array, the pure pipe doesn't execute. | To summarize, if you mutate the input array, the pure pipe doesn't execute. | ||||||
| If you *replace* the input array, the pipe executes and the display is updated, as shown in Figure 4. | If you *replace* the input array, the pipe executes and the display is updated. | ||||||
| 
 |  | ||||||
| <div class="lightbox"> |  | ||||||
|   <img src='generated/images/guide/pipes/flying-heroes-anim.gif' alt="Flying Heroes"> |  | ||||||
| </div> |  | ||||||
| 
 |  | ||||||
| **Figure 4.** The `flyingHeroes` pipe filtering the display to flying heroes |  | ||||||
| 
 | 
 | ||||||
| The above example demonstrates changing a component's code to accommodate a pipe. | The above example demonstrates changing a component's code to accommodate a pipe. | ||||||
| 
 | 
 | ||||||
| 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. | To keep your component 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. | ||||||
| 
 | 
 | ||||||
| {@a impure-flying-heroes} | {@a impure-flying-heroes} | ||||||
| 
 | 
 | ||||||
| @ -423,13 +408,20 @@ In the above example, a breakpoint on the pipe's request for data shows the foll | |||||||
| * Each binding gets its own pipe instance. | * Each binding gets its own pipe instance. | ||||||
| * Each pipe instance caches its own URL and data and calls the server only once. | * Each pipe instance caches its own URL and data and calls the server only once. | ||||||
| 
 | 
 | ||||||
| The `fetch` and `fetch-json` pipes display the heroes as shown in Figure 5. | The `fetch` and `fetch-json` pipes display the heroes in the browser as follows: | ||||||
| 
 | 
 | ||||||
| <div class="lightbox"> | <code-example language="none"> | ||||||
|   <img src='generated/images/guide/pipes/hero-list.png' alt="Hero List"> |  | ||||||
| </div> |  | ||||||
| 
 | 
 | ||||||
| **Figure 5.** The `fetch` and `fetch-json` pipes displaying the heroes | Heroes from JSON File | ||||||
|  | 
 | ||||||
|  | Windstorm | ||||||
|  | Bombasto | ||||||
|  | Magneto | ||||||
|  | Tornado | ||||||
|  | 
 | ||||||
|  | Heroes as JSON: [ { "name": "Windstorm", "canFly": true }, { "name": "Bombasto", "canFly": false }, { "name": "Magneto", "canFly": false }, { "name": "Tornado", "canFly": true } ] | ||||||
|  | 
 | ||||||
|  | </code-example> | ||||||
| 
 | 
 | ||||||
| <div class="alert is-helpful"> | <div class="alert is-helpful"> | ||||||
| 
 | 
 | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 12 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 53 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 7.1 KiB | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user