docs: improve accessibility of pipes example (#41317)

PR Close #41317
This commit is contained in:
Kapunahele Wong 2021-03-22 16:18:25 -04:00 committed by Jessica Janiuk
parent 8fe40026c1
commit 4ff636d24d
14 changed files with 83 additions and 79 deletions

View File

@ -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');
}); });
}); });

View File

@ -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>

View File

@ -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

View File

@ -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"
(keyup.enter)="addHero(box.value); box.value=''" id="hero-name"
placeholder="hero name"> #box
<input id="can-fly" type="checkbox" [(ngModel)]="canFly"> can fly (keyup.enter)="addHero(box.value); box.value=''"
</p> placeholder="hero name">
<p> <div>
<input id="can-fly" type="checkbox" [(ngModel)]="canFly">
<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}}

View File

@ -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
(keyup.enter)="addHero(box.value); box.value=''" id="hero-name"
placeholder="hero name"> (keyup.enter)="addHero(box.value); box.value=''"
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">

View File

@ -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)';

View File

@ -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>

View File

@ -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;

View File

@ -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 -->

View File

@ -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 {

View File

@ -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