docs(structural-directives): copyedits and some tweaks to code (#3345)

* docs(structural-directives): copyedits and some tweaks to code
- Fix variable name `li` --> `i`
- a --> an `UnlessDirective`
- Jade had both #ngswitch and #ngSwitch as link targets;
fixed to use same capitalization as template syntax page.
- Fixed broke fragment target (was missing #)
- Other copy edits and post-review comments from @wardbell
* de-sugar --> desugar
* fix h2 text capitalization
This commit is contained in:
Patrice Chalin 2017-03-09 17:30:23 -08:00 committed by Ward Bell
parent dfd360dc12
commit 7d17e342bb
4 changed files with 130 additions and 101 deletions

View File

@ -38,7 +38,7 @@
<!-- #docregion display-none -->
<p [style.display]="'block'">
Expression sets display to "block"" .
Expression sets display to "block".
This paragraph is visible.
</p>
<p [style.display]="'none'">
@ -152,11 +152,9 @@
<div>Pick your favorite hero</div>
<p>
<ng-container *ngFor="let h of heroes">
<label>
<label *ngFor="let h of heroes">
<input type="radio" name="heroes" [(ngModel)]="hero" [value]="h">{{h.name}}
</label>
</ng-container>
<label><input type="radio" name="heroes" (click)="hero = null">None of the above</label>
</p>

View File

@ -1,7 +1,6 @@
// #docplaster
// #docregion
// #docregion no-docs
// #docregion skeleton
// #docregion no-docs, skeleton
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
// #enddocregion skeleton
@ -18,7 +17,7 @@ import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
* </div>
*
* ### Syntax
* *
*
* - `<div *myUnless="condition">...</div>`
* - `<div template="myUnless condition">...</div>`
* - `<template [myUnless]="condition"><div>...</div></template>`
@ -50,6 +49,3 @@ export class UnlessDirective {
// #enddocregion set
// #docregion skeleton
}
// #enddocregion skeleton
// #enddocregion no-docs
// #enddocregion

View File

@ -147,7 +147,7 @@ figure.image-display
:marked
Notice the `hero` in the `ngFor` double-quoted instruction;
it is an example of a template input variable. Read
more about template input variables in the [microsyntax](./template-syntax.html#ngForMicrosyntax) section of
more about template input variables in the [microsyntax](./template-syntax.html#microsyntax) section of
the [Template Syntax](./template-syntax.html) page.
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable

View File

@ -1,7 +1,7 @@
block includes
include ../_util-fns
// The docs standard h4 style uppercases, making code terms unreadable. Override it.
//- The docs standard h4 style uppercases, making code terms unreadable. Override it.
style.
h4 {font-size: 17px !important; text-transform: none !important;}
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
@ -15,13 +15,13 @@ style.
- [What are structural directives?](#definition)
- [*NgIf* case study](#ngIf)
- [Group sibling elements with &lt;ng-container&gt;](#ng-container)
- [The asterisk (\*) prefix](#asterisk)
- [Inside *NgFor*](#ngfor)
- [The asterisk (*) prefix](#asterisk)
- [Inside *NgFor*](#ngFor)
- [microsyntax](#microsyntax)
- [template input variables](#template-input-variable)
- [one structural directive per element](#one-per-element)
- [Inside the *NgSwitch* directives](#ngSwitch)
- [Prefer the (\*) prefix](#prefer-asterisk)
- [Prefer the (*) prefix](#prefer-asterisk)
- [The &lt;template> element](#template)
- [Write a structural directive](#unless)
@ -40,14 +40,17 @@ a#definition
The directive then does whatever it's supposed to do with that host element and its descendents.
Structural directives are easy to recognize.
An asterisk (\*) precedes the directive attribute name as in this example.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif')(format=".")
An asterisk (*) precedes the directive attribute name as in this example.
+makeExcerpt('src/app/app.component.html', 'ngif', '')
:marked
No brackets. No parentheses. Just `*ngIf` set to a string.
You'll learn in this guide that the [asterisk (\*) is a convenience notation](#asterisk)
and the string is a [_microsyntax_](#microsyntax) rather than the usual [template expression](template-syntax.html#template-expressions).
Angular "de-sugars" this notation into a marked-up `<template>` that surrounds the
You'll learn in this guide that the [asterisk (*) is a convenience notation](#asterisk)
and the string is a [_microsyntax_](#microsyntax) rather than the usual
[template expression](template-syntax.html#template-expressions).
Angular desugars this notation into a marked-up `<template>` that surrounds the
host element and its descendents.
Each structural directive does something different with that template.
@ -56,7 +59,8 @@ a#definition
described in the [_Template Syntax_](template-syntax.html) guide and seen in samples throughout the Angular documentation.
Here's an example of them in a template:
+makeExample('structural-directives/ts/src/app/app.component.html', 'built-in')(format=".")
+makeExcerpt('src/app/app.component.html', 'built-in', '')
:marked
This guide won't repeat how to _use_ them. But it does explain _how they work_
and how to [write your own](#unless) structural directive.
@ -77,7 +81,8 @@ a#definition
.l-sub-section
:marked
There are two other kinds of Angular directives, described extensively elsewhere: (1)&nbsp;components and (2)&nbsp;attribute directives.
There are two other kinds of Angular directives, described extensively elsewhere:
(1)&nbsp;components and (2)&nbsp;attribute directives.
A *component* manages a region of HTML in the manner of a native HTML element.
Technically it's a directive with a template.
@ -93,12 +98,12 @@ a#definition
a#ngIf
.l-main-section
:marked
## NgIf Case Study
## NgIf case study
`NgIf` is the simplest structural directive and the easiest to understand.
It takes a boolean value and makes an entire chunk of the DOM appear or disappear.
It takes a boolean expression and makes an entire chunk of the DOM appear or disappear.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif-true')(format=".")
+makeExcerpt('src/app/app.component.html', 'ngif-true', '')
:marked
The `ngIf` directive doesn't hide elements with CSS. It adds and removes them physically from the DOM.
@ -119,13 +124,15 @@ figure.image-display
### Why *remove* rather than *hide*?
A directive could hide the unwanted paragraph instead by setting its `display` style to `none`.
+makeExample('structural-directives/ts/src/app/app.component.html', 'display-none')(format=".")
+makeExcerpt('src/app/app.component.html', 'display-none', '')
:marked
While invisible, the element remains in the DOM.
figure.image-display
img(src='/resources/images/devguide/structural-directives/element-display-in-dom.png' alt="hidden element still in DOM")
:marked
The difference between hiding and removing doesn't matter for a simple paragraph.
It does matter when the host element is attached to a resource intensive component.
@ -159,13 +166,13 @@ a#ng-container
There's often a _root_ element that can and should host the structural directive.
The list element (`<li>`) is a typical host element of an `NgFor` repeater.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngfor-li')(format=".")
+makeExcerpt('src/app/app.component.html', 'ngfor-li', '')
:marked
When there isn't a host element, you can usually wrap the content in a native HTML container element,
such as a `<div>`, and attach the directive to that wrapper.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif')(format=".")
+makeExcerpt('src/app/app.component.html', 'ngif', '')
:marked
Introducing another container element&mdash;typically a `<span>` or `<div>`&mdash;to
@ -175,27 +182,37 @@ a#ng-container
The grouping element may break the template appearance because CSS styles
neither expect nor accommodate the new layout.
For example, suppose you have the following paragraph layout.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif-span')(format=".")
+makeExcerpt('src/app/app.component.html', 'ngif-span', '')
:marked
You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
+makeExample('structural-directives/ts/src/app/app.component.css', 'p-span')(format=".")
+makeExcerpt('src/app/app.component.css', 'p-span', '')
:marked
The constructed paragraph renders strangely.
figure.image-display
img(src='/resources/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style")
:marked
The `p span` style, intended for use elsewhere, was inadvertently applied here.
Another problem: some HTML elements require all immediate children to be of a specific type.
For example, the `<select>` tag requires `<option>` children.
For example, the `<select>` element requires `<option>` children.
You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
When you try this,
+makeExample('structural-directives/ts/src/app/app.component.html', 'select-span')(format=".")
+makeExcerpt('src/app/app.component.html', 'select-span', '')
:marked
the drop down is empty.
figure.image-display
img(src='/resources/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work")
:marked
The browser won't display an `<option>` within a `<span>`.
@ -205,16 +222,23 @@ figure.image-display
because Angular _doesn't put it in the DOM_.
Here's the conditional paragraph again, this time using `<ng-container>`.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif-ngcontainer')(format=".")
+makeExcerpt('src/app/app.component.html', 'ngif-ngcontainer', '')
:marked
It renders properly.
figure.image-display
img(src='/resources/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style")
:marked
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
+makeExample('structural-directives/ts/src/app/app.component.html', 'select-ngcontainer')(format=".")
+makeExcerpt('src/app/app.component.html', 'select-ngcontainer', '')
:marked
The drop down works properly.
figure.image-display
img(src='/resources/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly")
@ -229,46 +253,43 @@ code-example(language="javascript").
statement2;
statement3;
}
:marked
Without those braces JavaScript could only execute the first statement
Without those braces, JavaScript would only execute the first statement
when you intend to conditionally execute all of them as a single block.
The `<ng-container>` satisfies a similar need in Angular templates.
a#asterisk
.l-main-section
:marked
## The asterisk (\*) prefix
## The asterisk (*) prefix
Surely you noticed the asterisk (\*) prefix to the directive name
Surely you noticed the asterisk (*) prefix to the directive name
and wondered why it is necessary and what it does.
Here is `*ngIf` displaying the hero's name if `hero` exists.
+makeExample('structural-directives/ts/src/app/app.component.html', 'asterisk')(format=".")
+makeExcerpt('src/app/app.component.html', 'asterisk', '')
:marked
The asterisk is "syntactic sugar" for something a bit more complicated.
Internally, Angular "de-sugars" it in two stages.
Internally, Angular "desugars" it in two stages.
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`,&nbsp; like this.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif-template-attr')(format=".")
+makeExcerpt('src/app/app.component.html', 'ngif-template-attr', '')
:marked
Then it translates the template _attribute_ into a template _element_, wrapped around the host element, like this.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif-template')(format=".")
// We should discourage writing <template> syntax in favor of <ng-container>
block remember-the-brackets
.alert.is-critical
:marked
Write `[ngIf]="hero"`, not `ngIf="hero"`!
The latter incorrectly assigns the *string* `"hero"` to `ngIf`.
A non-empty string is _truthy_, so `ngIf` is always `true` and Angular
always tries to show the content … even when there is no `hero`.
+makeExcerpt('src/app/app.component.html', 'ngif-template', '')
:marked
* The `*ngIf` directive moved to the `<template>` tag where it became a property binding,`[ngIf]`.
* The rest of the `<div>`, including its class attribute, moved inside the `<template>` tag.
* The `*ngIf` directive moved to the `<template>` element where it became a property binding,`[ngIf]`.
* The rest of the `<div>`, including its class attribute, moved inside the `<template>` element.
None of these forms are actually rendered.
Only the finished product ends up in the DOM.
figure.image-display
img(src='/resources/images/devguide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM")
@ -276,25 +297,26 @@ figure.image-display
Angular consumed the `<template>` content during its actual rendering and
replaced the `<template>` with a diagnostic comment.
The [`NgFor`](#ngfor) and [`NgSwitch...`](#ngswitch) directives follow the same pattern.
The [`NgFor`](#ngFor) and [`NgSwitch...`](#ngSwitch) directives follow the same pattern.
a#ngfor
.l-main-section
:marked
## Inside _*ngFor_
Angular transforms the `*ngFor` in similar fashion from asterisk (\*) syntax through
Angular transforms the `*ngFor` in similar fashion from asterisk (*) syntax through
template _attribute_ to template _element_.
Here's a full-featured application of `NgFor`, written all three ways:
+makeExample('structural-directives/ts/src/app/app.component.html', 'inside-ngfor')(format=".")
+makeExcerpt('src/app/app.component.html', 'inside-ngfor', '')
:marked
This is manifestly more complicated than `ngIf` and rightly so.
The `NgFor` directive has more features, both required and optional, than the `NgIf` shown in this guide.
At minimum `NgFor` needs a looping variable (`let hero`) and a list (`heroes`).
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](microsyntax).
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](#microsyntax).
.alert.is-helpful
:marked
@ -304,7 +326,8 @@ a#ngfor
a#microsyntax
:marked
### microsyntax
### Microsyntax
The Angular microsyntax lets you configure a directive in a compact, friendly string.
The microsyntax parser translates that string into attributes on the `<template>`:
@ -342,18 +365,18 @@ a#template-input-variables
### Template input variable
A _template input variable_ is a variable whose value you can reference _within_ a single instance of the template.
There are several such variables in this example: `hero`, `li`, and `odd`.
There are several such variables in this example: `hero`, `i`, and `odd`.
All are preceded by the keyword `let`.
A _template input variable_ is **_not_** the same as a
[template _reference_ variable](template-syntax.html#ref-vars),
neither _semantically_ nor _syntactically_.
You declare a template _input_ variable declaration with the `let` keyword (`let hero`).
You declare a template _input_ variable using the `let` keyword (`let hero`).
The variable's scope is limited to a _single instance_ of the repeated template.
You can use the same variable name again in the definition of other structural directives.
You declare a template _reference_ variable declaration by prefixing the variable name with `#` (`#var`).
You declare a template _reference_ variable by prefixing the variable name with `#` (`#var`).
A _reference_ variable refers to its attached element, component or directive.
It can be accessed _anywhere_ in the _entire template_.
@ -380,12 +403,13 @@ a#one-per-element
a#ngswitch
.l-main-section
:marked
## Inside the _NgSwitch_ directives
## Inside _NgSwitch_ directives
The Angular _NgSwitch_ is actually a set of cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault`.
Here's an example.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngswitch')(format=".")
+makeExcerpt('src/app/app.component.html', 'ngswitch', '')
:marked
The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
@ -396,7 +420,7 @@ a#ngswitch
That's why you write `[ngSwitch]`, never `*ngSwitch`.
`NgSwitchCase` and `NgSwitchDefault` _are_ structural directives.
You attach them to elements using the asterisk (\*) prefix notation.
You attach them to elements using the asterisk (*) prefix notation.
An `NgSwitchCase` displays its host element when its value matches the switch value.
The `NgSwitchDefault` displays its host element when no sibling `NgSwitchCase` matches the switch value.
@ -408,17 +432,20 @@ a#ngswitch
:marked
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
can be "de-sugared" into the template _attribute_ form.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngswitch-template-attr')(format=".")
can be desugared into the template _attribute_ form.
+makeExcerpt('src/app/app.component.html', 'ngswitch-template-attr', '')
:marked
That, in turn, can be "de-sugared" into the `<template>` element form.
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngswitch-template')(format=".")
That, in turn, can be desugared into the `<template>` element form.
+makeExcerpt('src/app/app.component.html', 'ngswitch-template', '')
a#prefer-asterisk
:marked
## Prefer the asterisk (\*) syntax.
## Prefer the asterisk (*) syntax.
The asterisk (\*) syntax is more clear than the other "de-sugared" forms.
The asterisk (*) syntax is more clear than the other desugared forms.
Use [&lt;ng-container&gt;](#ng-container) when there's no single element
to host the directive.
@ -436,12 +463,15 @@ a#template
It is never displayed directly.
In fact, before rendering the view, Angular _replaces_ the `<template>` and its contents with a comment.
If there is no structural directive, if you merely wrap some elements in a `<template>` and do nothing with it,
If there is no structural directive and you merely wrap some elements in a `<template>`,
those elements disappear.
That's the fate of the middle "hip" in the phrase "Hip! Hip! Hooray!".
+makeExample('structural-directives/ts/src/app/app.component.html', 'template-tag')(format=".")
That's the fate of the middle "Hip!" in the phrase "Hip! Hip! Hooray!".
+makeExcerpt('src/app/app.component.html', 'template-tag', '')
:marked
Angular erases the middle "hip", leaving the cheer a bit less enthusiastic.
Angular erases the middle "Hip!", leaving the cheer a bit less enthusiastic.
figure.image-display
img(src='/resources/images/devguide/structural-directives/template-rendering.png' width="350" alt="template tag rendering")
@ -453,15 +483,14 @@ a#unless
.l-main-section
:marked
## Write a structural directive
In this section, you write a `UnlessDirective` structural directive
In this section, you write an `UnlessDirective` structural directive
that does the opposite of `NgIf`.
`NgIf` displays the template content when the condition is `true`.
`UnlessDirective` displays the content when the condition is ***false***.
+makeExample('structural-directives/ts/src/app/app.component.html', 'myUnless-1')(format=".")
:marked
+makeExcerpt('src/app/app.component.html', 'myUnless-1', '')
block unless-intro
:marked
Creating a directive is similar to creating a component.
@ -475,10 +504,10 @@ block unless-intro
Here's how you might begin:
+makeExample('structural-directives/ts/src/app/unless.directive.ts', 'skeleton', 'unless.directive.ts (skeleton)')(format=".")
+makeExcerpt('src/app/unless.directive.ts (skeleton)')
:marked
The directive's _selector_ is typically the directive's **attribute name** in square brackets.`[myUnless]`.
The directive's _selector_ is typically the directive's **attribute name** in square brackets, `[myUnless]`.
The brackets define a CSS
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors" target="_blank" title="MDN: Attribute selectors">attribute selector</a>.
@ -506,18 +535,20 @@ block unless-intro
You inject both in the directive constructor as private variables of the class.
+makeExample('structural-directives/ts/src/app/unless.directive.ts', 'ctor')(format=".")
+makeExcerpt('src/app/unless.directive.ts', 'ctor', '')
:marked
### The _myUnless_ property
The directive consumer expects to bind a true/false condition to `[myUnless]`.
That means the directive needs a `myUnless` property, decorated with `@Input`
.l-sub-section
:marked
Read about `@Input` in the [_Template Syntax_](template-syntax.html#inputs-outputs) guide.
+makeExample('structural-directives/ts/src/app/unless.directive.ts', 'set')(format=".")
+makeExcerpt('src/app/unless.directive.ts', 'set', '')
:marked
Angular sets the `myUnless` property whenever the value of the condition changes.
Because the `myUnless` property does work, it needs a setter.
@ -532,16 +563,19 @@ block unless-intro
The completed directive code looks like this:
+makeExample('structural-directives/ts/src/app/unless.directive.ts', 'no-docs', 'unless.directive.ts')
+makeExcerpt('src/app/unless.directive.ts (excerpt)', 'no-docs')
:marked
Add this directive to the `!{_declsVsDirectives}` !{_array} of the !{_AppModuleVsAppComp}.
Then create some HTML to try it.
+makeExample('structural-directives/ts/src/app/app.component.html', 'myUnless')(format=".")
+makeExcerpt('src/app/app.component.html', 'myUnless', '')
:marked
When the `condition` is falsy, the top (A) paragraph appears and the bottom (B) paragraph disappears.
When the `condition` is truthy, the top (A) paragraph is removed and the bottom (B) paragraph appears.
figure.image-display
img(src='/resources/images/devguide/structural-directives/unless-anim.gif' alt="UnlessDirective in action" )
@ -551,7 +585,7 @@ a#summary
## Summary
You can both try and download the source code for this guide in the <live-example></live-example>.
Here is the source from the `app/` folder.
Here is the source from the `src/app/` folder.
+makeTabs(`
structural-directives/ts/src/app/app.component.ts,
@ -574,9 +608,10 @@ a#summary
:marked
You learned
* that structural directives manipulate HTML layout.
* to use [`<ng-container>`](#ngcontainer) as a grouping element when there is no suitable host element.
* that the angular "de-sugars" [asterisk (\*) syntax](#asterisk) into a `<template>`.
* that the Angular "desugars" [asterisk (*) syntax](#asterisk) into a `<template>`.
* how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives.
* about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template).
* to write a [custom structural directive](#unless), `UnlessDirective`.