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 () => {
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>
<h1>Pipes</h1>
<a href="#happy-birthday1">Happy Birthday v1</a><br>
<a href="#birthday-date-pipe">Birthday DatePipe</a><br>
<a href="#happy-birthday2">Happy Birthday v2</a><br>
<a href="#birthday-pipe-chaining">Birthday Pipe Chaining</a><br>
<a href="#power-booster">Power Booster custom pipe</a><br>
<a href="#power-boost-calc">Power Boost Calculator custom pipe with params</a><br>
<a href="#flying-heroes">Flying Heroes filter pipe (pure)</a><br>
<a href="#flying-heroes-impure">Flying Heroes filter pipe (impure)</a><br>
<a href="#hero-message">Async Hero Message and AsyncPipe</a><br>
<a href="#hero-list">Hero List with caching FetchJsonPipe</a><br>
<a href="#pipe-precedence">Pipes and Precedence</a><br>
<a href="#happy-birthday1">Happy Birthday v1</a>
<a href="#birthday-date-pipe">Birthday DatePipe</a>
<a href="#happy-birthday2">Happy Birthday v2</a>
<a href="#birthday-pipe-chaining">Birthday Pipe Chaining</a>
<a href="#power-booster">Power Booster custom pipe</a>
<a href="#power-boost-calc">Power Boost Calculator custom pipe with params</a>
<a href="#flying-heroes">Flying Heroes filter pipe (pure)</a>
<a href="#flying-heroes-impure">Flying Heroes filter pipe (impure)</a>
<a href="#hero-message">Async Hero Message and AsyncPipe</a>
<a href="#hero-list">Hero List with caching FetchJsonPipe</a>
<a href="#pipe-precedence">Pipes and Precedence</a>
<hr>
@ -73,7 +73,7 @@
<hr>
<a id="hero-message"></a>
<!-- 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>
<a id="hero-list"></a>

View File

@ -3,7 +3,8 @@ import { Component } from '@angular/core';
@Component({
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 {
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based

View File

@ -1,19 +1,24 @@
<!-- #docplaster-->
<!-- #docregion -->
<h2>{{title}}</h2>
<p>
New hero:
<input type="text" #box
(keyup.enter)="addHero(box.value); box.value=''"
placeholder="hero name">
<input id="can-fly" type="checkbox" [(ngModel)]="canFly"> can fly
</p>
<p>
<label for="hero-name">New hero: </label>
<input type="text"
id="hero-name"
#box
(keyup.enter)="addHero(box.value); box.value=''"
placeholder="hero name">
<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
<button (click)="reset()">Reset</button>
</p>
</div>
<h4>Heroes who fly (piped)</h4>
<h3>Heroes who fly (piped)</h3>
<div id="flyers">
<!-- #docregion template-flying-heroes -->
<div *ngFor="let hero of (heroes | flyingHeroesImpure)">
@ -22,7 +27,7 @@ New hero:
<!-- #enddocregion template-flying-heroes -->
</div>
<h4>All Heroes (no pipe)</h4>
<h3>All Heroes (no pipe)</h3>
<div id="all">
<div *ngFor="let hero of heroes">
{{hero.name}}

View File

@ -1,23 +1,27 @@
<!-- #docplaster-->
<!-- #docregion -->
<h2>{{title}}</h2>
<p>
<p>Create a new hero and press enter to add it to the list. </p>
<!-- #docregion template-1 -->
New hero:
<input type="text" #box
(keyup.enter)="addHero(box.value); box.value=''"
placeholder="hero name">
<label for="hero-name">New hero name: </label>
<input type="text" #box
id="hero-name"
(keyup.enter)="addHero(box.value); box.value=''"
placeholder="hero name">
<!-- #enddocregion template-1 -->
<input id="can-fly" type="checkbox" [(ngModel)]="canFly"> can fly
</p>
<p>
<input id="mutate" type="checkbox" [(ngModel)]="mutate">Mutate array
<div>
<input id="can-fly" type="checkbox" [(ngModel)]="canFly">
<label for="can-fly">Hero can fly</label>
</div>
<div>
<input id="mutate" type="checkbox" [(ngModel)]="mutate">
<label for="mutate">Mutate array</label>
<!-- #docregion template-1 -->
<button (click)="reset()">Reset</button>
<button (click)="reset()">Reset list of heroes</button>
<!-- #enddocregion template-1 -->
</p>
</div>
<h4>Heroes who fly (piped)</h4>
<h3>Heroes who fly (piped)</h3>
<div id="flyers">
<!-- #docregion template-flying-heroes -->
<div *ngFor="let hero of (heroes | flyingHeroes)">
@ -26,7 +30,7 @@ New hero:
<!-- #enddocregion template-flying-heroes -->
</div>
<h4>All Heroes (no pipe)</h4>
<h3>All Heroes (no pipe)</h3>
<div id="all">
<!-- #docregion template-1 -->
<div *ngFor="let hero of heroes">

View File

@ -7,7 +7,7 @@ import { HEROES } from './heroes';
@Component({
selector: 'app-flying-heroes',
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
export class FlyingHeroesComponent {
@ -48,7 +48,7 @@ export class FlyingHeroesComponent {
@Component({
selector: 'app-flying-heroes-impure',
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 {
title = 'Flying Heroes (impure pipe)';

View File

@ -5,7 +5,7 @@ import { Observable, interval } from 'rxjs';
import { map, take } from 'rxjs/operators';
@Component({
selector: 'app-hero-message',
selector: 'app-hero-async-message',
template: `
<h2>Async Hero Message and AsyncPipe</h2>
<p>Message: {{ message$ | async }}</p>

View File

@ -5,12 +5,15 @@ import { Component } from '@angular/core';
selector: 'app-power-boost-calculator',
template: `
<h2>Power Boost Calculator</h2>
<div>Normal power: <input [(ngModel)]="power"></div>
<div>Boost factor: <input [(ngModel)]="factor"></div>
<label for="power-input">Normal power: </label>
<input id="power-input" type="text" [(ngModel)]="power">
<label for="boost-input">Boost factor: </label>
<input id="boost-input" type="text" [(ngModel)]="factor">
<p>
Super Hero Power: {{power | exponentialStrength: factor}}
</p>
`
`,
styles: ['input {margin: .5rem 0;}']
})
export class PowerBoostCalculatorComponent {
power = 5;

View File

@ -3,7 +3,7 @@
<h2>{{title}}</h2>
<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:
<!-- #docregion precedence -->
<!-- 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({
selector: 'app-precedence',
templateUrl: './precedence.component.html',
styles: []
templateUrl: './precedence.component.html'
})
export class PrecedenceComponent {

View File

@ -100,13 +100,7 @@ The tabs in the following example demonstrates toggling between two different fo
</code-pane>
</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.
<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
Clicking the **Toggle Format** button alternates the date format between **04/15/1988** and **Friday, April 15, 1988**.
<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.
* 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-pane
@ -189,11 +182,15 @@ Figure 2 shows the output.
</code-pane>
</code-tabs>
<div class="lightbox">
<img src='generated/images/guide/pipes/power-booster.png' alt="Power Booster">
</div>
The browser displays the following:
**Figure 2.** Output from the `exponentialStrength` pipe
<code-example language="none">
Power Booster
Superpower boost: 1024
</code-example>
<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>
The `exponentialStrength` pipe executes every time the user changes the "normal power" value or the "boost factor", as shown in Figure 3.
<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
The `exponentialStrength` pipe executes every time the user changes the "normal power" value or the "boost factor".
Angular detects each change and immediately runs the pipe.
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.
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.
<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
If you *replace* the input array, the pipe executes and the display is updated.
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}
@ -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 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">
<img src='generated/images/guide/pipes/hero-list.png' alt="Hero List">
</div>
<code-example language="none">
**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">

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