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:
parent
dfd360dc12
commit
7d17e342bb
|
@ -38,11 +38,11 @@
|
||||||
|
|
||||||
<!-- #docregion display-none -->
|
<!-- #docregion display-none -->
|
||||||
<p [style.display]="'block'">
|
<p [style.display]="'block'">
|
||||||
Expression sets display to "block"" .
|
Expression sets display to "block".
|
||||||
This paragraph is visible.
|
This paragraph is visible.
|
||||||
</p>
|
</p>
|
||||||
<p [style.display]="'none'">
|
<p [style.display]="'none'">
|
||||||
Expression sets display to "none" .
|
Expression sets display to "none".
|
||||||
This paragraph is hidden but still in the DOM.
|
This paragraph is hidden but still in the DOM.
|
||||||
</p>
|
</p>
|
||||||
<!-- #enddocregion display-none -->
|
<!-- #enddocregion display-none -->
|
||||||
|
@ -152,11 +152,9 @@
|
||||||
|
|
||||||
<div>Pick your favorite hero</div>
|
<div>Pick your favorite hero</div>
|
||||||
<p>
|
<p>
|
||||||
<ng-container *ngFor="let h of heroes">
|
<label *ngFor="let h of heroes">
|
||||||
<label>
|
|
||||||
<input type="radio" name="heroes" [(ngModel)]="hero" [value]="h">{{h.name}}
|
<input type="radio" name="heroes" [(ngModel)]="hero" [value]="h">{{h.name}}
|
||||||
</label>
|
</label>
|
||||||
</ng-container>
|
|
||||||
<label><input type="radio" name="heroes" (click)="hero = null">None of the above</label>
|
<label><input type="radio" name="heroes" (click)="hero = null">None of the above</label>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion no-docs
|
// #docregion no-docs, skeleton
|
||||||
// #docregion skeleton
|
|
||||||
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
||||||
|
|
||||||
// #enddocregion skeleton
|
// #enddocregion skeleton
|
||||||
|
@ -18,7 +17,7 @@ import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
||||||
* </div>
|
* </div>
|
||||||
*
|
*
|
||||||
* ### Syntax
|
* ### Syntax
|
||||||
* *
|
*
|
||||||
* - `<div *myUnless="condition">...</div>`
|
* - `<div *myUnless="condition">...</div>`
|
||||||
* - `<div template="myUnless condition">...</div>`
|
* - `<div template="myUnless condition">...</div>`
|
||||||
* - `<template [myUnless]="condition"><div>...</div></template>`
|
* - `<template [myUnless]="condition"><div>...</div></template>`
|
||||||
|
@ -50,6 +49,3 @@ export class UnlessDirective {
|
||||||
// #enddocregion set
|
// #enddocregion set
|
||||||
// #docregion skeleton
|
// #docregion skeleton
|
||||||
}
|
}
|
||||||
// #enddocregion skeleton
|
|
||||||
// #enddocregion no-docs
|
|
||||||
// #enddocregion
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ figure.image-display
|
||||||
:marked
|
:marked
|
||||||
Notice the `hero` in the `ngFor` double-quoted instruction;
|
Notice the `hero` in the `ngFor` double-quoted instruction;
|
||||||
it is an example of a template input variable. Read
|
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.
|
the [Template Syntax](./template-syntax.html) page.
|
||||||
|
|
||||||
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
|
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
block includes
|
block includes
|
||||||
include ../_util-fns
|
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.
|
style.
|
||||||
h4 {font-size: 17px !important; text-transform: none !important;}
|
h4 {font-size: 17px !important; text-transform: none !important;}
|
||||||
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
||||||
|
@ -15,13 +15,13 @@ style.
|
||||||
- [What are structural directives?](#definition)
|
- [What are structural directives?](#definition)
|
||||||
- [*NgIf* case study](#ngIf)
|
- [*NgIf* case study](#ngIf)
|
||||||
- [Group sibling elements with <ng-container>](#ng-container)
|
- [Group sibling elements with <ng-container>](#ng-container)
|
||||||
- [The asterisk (\*) prefix](#asterisk)
|
- [The asterisk (*) prefix](#asterisk)
|
||||||
- [Inside *NgFor*](#ngfor)
|
- [Inside *NgFor*](#ngFor)
|
||||||
- [microsyntax](#microsyntax)
|
- [microsyntax](#microsyntax)
|
||||||
- [template input variables](#template-input-variable)
|
- [template input variables](#template-input-variable)
|
||||||
- [one structural directive per element](#one-per-element)
|
- [one structural directive per element](#one-per-element)
|
||||||
- [Inside the *NgSwitch* directives](#ngSwitch)
|
- [Inside the *NgSwitch* directives](#ngSwitch)
|
||||||
- [Prefer the (\*) prefix](#prefer-asterisk)
|
- [Prefer the (*) prefix](#prefer-asterisk)
|
||||||
- [The <template> element](#template)
|
- [The <template> element](#template)
|
||||||
- [Write a structural directive](#unless)
|
- [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.
|
The directive then does whatever it's supposed to do with that host element and its descendents.
|
||||||
|
|
||||||
Structural directives are easy to recognize.
|
Structural directives are easy to recognize.
|
||||||
An asterisk (\*) precedes the directive attribute name as in this example.
|
An asterisk (*) precedes the directive attribute name as in this example.
|
||||||
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngif')(format=".")
|
|
||||||
|
+makeExcerpt('src/app/app.component.html', 'ngif', '')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
No brackets. No parentheses. Just `*ngIf` set to a string.
|
No brackets. No parentheses. Just `*ngIf` set to a string.
|
||||||
|
|
||||||
You'll learn in this guide that the [asterisk (\*) is a convenience notation](#asterisk)
|
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).
|
and the string is a [_microsyntax_](#microsyntax) rather than the usual
|
||||||
Angular "de-sugars" this notation into a marked-up `<template>` that surrounds the
|
[template expression](template-syntax.html#template-expressions).
|
||||||
|
Angular desugars this notation into a marked-up `<template>` that surrounds the
|
||||||
host element and its descendents.
|
host element and its descendents.
|
||||||
Each structural directive does something different with that template.
|
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.
|
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:
|
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
|
:marked
|
||||||
This guide won't repeat how to _use_ them. But it does explain _how they work_
|
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.
|
and how to [write your own](#unless) structural directive.
|
||||||
|
@ -77,7 +81,8 @@ a#definition
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
There are two other kinds of Angular directives, described extensively elsewhere: (1) components and (2) attribute directives.
|
There are two other kinds of Angular directives, described extensively elsewhere:
|
||||||
|
(1) components and (2) attribute directives.
|
||||||
|
|
||||||
A *component* manages a region of HTML in the manner of a native HTML element.
|
A *component* manages a region of HTML in the manner of a native HTML element.
|
||||||
Technically it's a directive with a template.
|
Technically it's a directive with a template.
|
||||||
|
@ -93,12 +98,12 @@ a#definition
|
||||||
a#ngIf
|
a#ngIf
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## NgIf Case Study
|
## NgIf case study
|
||||||
|
|
||||||
`NgIf` is the simplest structural directive and the easiest to understand.
|
`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
|
:marked
|
||||||
The `ngIf` directive doesn't hide elements with CSS. It adds and removes them physically from the DOM.
|
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*?
|
### Why *remove* rather than *hide*?
|
||||||
|
|
||||||
A directive could hide the unwanted paragraph instead by setting its `display` style to `none`.
|
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
|
:marked
|
||||||
While invisible, the element remains in the DOM.
|
While invisible, the element remains in the DOM.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/element-display-in-dom.png' alt="hidden element still in DOM")
|
img(src='/resources/images/devguide/structural-directives/element-display-in-dom.png' alt="hidden element still in DOM")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The difference between hiding and removing doesn't matter for a simple paragraph.
|
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.
|
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.
|
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.
|
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
|
:marked
|
||||||
When there isn't a host element, you can usually wrap the content in a native HTML container element,
|
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.
|
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
|
:marked
|
||||||
Introducing another container element—typically a `<span>` or `<div>`—to
|
Introducing another container element—typically a `<span>` or `<div>`—to
|
||||||
|
@ -175,27 +182,37 @@ a#ng-container
|
||||||
The grouping element may break the template appearance because CSS styles
|
The grouping element may break the template appearance because CSS styles
|
||||||
neither expect nor accommodate the new layout.
|
neither expect nor accommodate the new layout.
|
||||||
For example, suppose you have the following paragraph 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
|
:marked
|
||||||
You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
|
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
|
:marked
|
||||||
The constructed paragraph renders strangely.
|
The constructed paragraph renders strangely.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style")
|
img(src='/resources/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The `p span` style, intended for use elsewhere, was inadvertently applied here.
|
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.
|
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>`.
|
You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
|
||||||
|
|
||||||
When you try this,
|
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
|
:marked
|
||||||
the drop down is empty.
|
the drop down is empty.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work")
|
img(src='/resources/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The browser won't display an `<option>` within a `<span>`.
|
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_.
|
because Angular _doesn't put it in the DOM_.
|
||||||
|
|
||||||
Here's the conditional paragraph again, this time using `<ng-container>`.
|
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
|
:marked
|
||||||
It renders properly.
|
It renders properly.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style")
|
img(src='/resources/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
|
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
|
:marked
|
||||||
The drop down works properly.
|
The drop down works properly.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly")
|
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;
|
statement2;
|
||||||
statement3;
|
statement3;
|
||||||
}
|
}
|
||||||
|
|
||||||
:marked
|
: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.
|
when you intend to conditionally execute all of them as a single block.
|
||||||
The `<ng-container>` satisfies a similar need in Angular templates.
|
The `<ng-container>` satisfies a similar need in Angular templates.
|
||||||
|
|
||||||
a#asterisk
|
a#asterisk
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
: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.
|
and wondered why it is necessary and what it does.
|
||||||
|
|
||||||
Here is `*ngIf` displaying the hero's name if `hero` exists.
|
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
|
:marked
|
||||||
The asterisk is "syntactic sugar" for something a bit more complicated.
|
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 ..."`, like this.
|
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`, 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
|
:marked
|
||||||
Then it translates the template _attribute_ into a template _element_, wrapped around the host element, like this.
|
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>
|
+makeExcerpt('src/app/app.component.html', 'ngif-template', '')
|
||||||
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`.
|
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
* The `*ngIf` directive moved to the `<template>` tag where it became a property binding,`[ngIf]`.
|
* 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>` tag.
|
* The rest of the `<div>`, including its class attribute, moved inside the `<template>` element.
|
||||||
|
|
||||||
None of these forms are actually rendered.
|
None of these forms are actually rendered.
|
||||||
Only the finished product ends up in the DOM.
|
Only the finished product ends up in the DOM.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM")
|
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
|
Angular consumed the `<template>` content during its actual rendering and
|
||||||
replaced the `<template>` with a diagnostic comment.
|
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
|
a#ngfor
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Inside _*ngFor_
|
## 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_.
|
template _attribute_ to template _element_.
|
||||||
|
|
||||||
Here's a full-featured application of `NgFor`, written all three ways:
|
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
|
:marked
|
||||||
This is manifestly more complicated than `ngIf` and rightly so.
|
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.
|
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`).
|
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
|
.alert.is-helpful
|
||||||
:marked
|
:marked
|
||||||
|
@ -304,7 +326,8 @@ a#ngfor
|
||||||
|
|
||||||
a#microsyntax
|
a#microsyntax
|
||||||
:marked
|
:marked
|
||||||
### microsyntax
|
### Microsyntax
|
||||||
|
|
||||||
The Angular microsyntax lets you configure a directive in a compact, friendly string.
|
The Angular microsyntax lets you configure a directive in a compact, friendly string.
|
||||||
The microsyntax parser translates that string into attributes on the `<template>`:
|
The microsyntax parser translates that string into attributes on the `<template>`:
|
||||||
|
|
||||||
|
@ -342,18 +365,18 @@ a#template-input-variables
|
||||||
### Template input variable
|
### Template input variable
|
||||||
|
|
||||||
A _template input variable_ is a variable whose value you can reference _within_ a single instance of the template.
|
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`.
|
All are preceded by the keyword `let`.
|
||||||
|
|
||||||
A _template input variable_ is **_not_** the same as a
|
A _template input variable_ is **_not_** the same as a
|
||||||
[template _reference_ variable](template-syntax.html#ref-vars),
|
[template _reference_ variable](template-syntax.html#ref-vars),
|
||||||
neither _semantically_ nor _syntactically_.
|
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.
|
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 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.
|
A _reference_ variable refers to its attached element, component or directive.
|
||||||
It can be accessed _anywhere_ in the _entire template_.
|
It can be accessed _anywhere_ in the _entire template_.
|
||||||
|
|
||||||
|
@ -380,12 +403,13 @@ a#one-per-element
|
||||||
a#ngswitch
|
a#ngswitch
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Inside the _NgSwitch_ directives
|
## Inside _NgSwitch_ directives
|
||||||
|
|
||||||
The Angular _NgSwitch_ is actually a set of cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault`.
|
The Angular _NgSwitch_ is actually a set of cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault`.
|
||||||
|
|
||||||
Here's an example.
|
Here's an example.
|
||||||
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngswitch')(format=".")
|
|
||||||
|
+makeExcerpt('src/app/app.component.html', 'ngswitch', '')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
|
The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
|
||||||
|
@ -396,7 +420,7 @@ a#ngswitch
|
||||||
That's why you write `[ngSwitch]`, never `*ngSwitch`.
|
That's why you write `[ngSwitch]`, never `*ngSwitch`.
|
||||||
|
|
||||||
`NgSwitchCase` and `NgSwitchDefault` _are_ structural directives.
|
`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.
|
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.
|
The `NgSwitchDefault` displays its host element when no sibling `NgSwitchCase` matches the switch value.
|
||||||
|
|
||||||
|
@ -408,17 +432,20 @@ a#ngswitch
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
|
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
|
||||||
can be "de-sugared" into the template _attribute_ form.
|
can be desugared into the template _attribute_ form.
|
||||||
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngswitch-template-attr')(format=".")
|
|
||||||
|
+makeExcerpt('src/app/app.component.html', 'ngswitch-template-attr', '')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
That, in turn, can be "de-sugared" into the `<template>` element form.
|
That, in turn, can be desugared into the `<template>` element form.
|
||||||
+makeExample('structural-directives/ts/src/app/app.component.html', 'ngswitch-template')(format=".")
|
|
||||||
|
+makeExcerpt('src/app/app.component.html', 'ngswitch-template', '')
|
||||||
|
|
||||||
a#prefer-asterisk
|
a#prefer-asterisk
|
||||||
:marked
|
: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 [<ng-container>](#ng-container) when there's no single element
|
Use [<ng-container>](#ng-container) when there's no single element
|
||||||
to host the directive.
|
to host the directive.
|
||||||
|
|
||||||
|
@ -436,12 +463,15 @@ a#template
|
||||||
It is never displayed directly.
|
It is never displayed directly.
|
||||||
In fact, before rendering the view, Angular _replaces_ the `<template>` and its contents with a comment.
|
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.
|
those elements disappear.
|
||||||
That's the fate of the middle "hip" in the phrase "Hip! Hip! Hooray!".
|
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=".")
|
|
||||||
|
+makeExcerpt('src/app/app.component.html', 'template-tag', '')
|
||||||
|
|
||||||
:marked
|
: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
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/template-rendering.png' width="350" alt="template tag rendering")
|
img(src='/resources/images/devguide/structural-directives/template-rendering.png' width="350" alt="template tag rendering")
|
||||||
|
|
||||||
|
@ -453,16 +483,15 @@ a#unless
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Write a structural directive
|
## 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`.
|
that does the opposite of `NgIf`.
|
||||||
`NgIf` displays the template content when the condition is `true`.
|
`NgIf` displays the template content when the condition is `true`.
|
||||||
`UnlessDirective` displays the content when the condition is ***false***.
|
`UnlessDirective` displays the content when the condition is ***false***.
|
||||||
|
|
||||||
+makeExample('structural-directives/ts/src/app/app.component.html', 'myUnless-1')(format=".")
|
+makeExcerpt('src/app/app.component.html', 'myUnless-1', '')
|
||||||
:marked
|
|
||||||
|
|
||||||
block unless-intro
|
:marked
|
||||||
:marked
|
|
||||||
Creating a directive is similar to creating a component.
|
Creating a directive is similar to creating a component.
|
||||||
|
|
||||||
* Import the `Directive` decorator (instead of the `Component` decorator).
|
* Import the `Directive` decorator (instead of the `Component` decorator).
|
||||||
|
@ -475,10 +504,10 @@ block unless-intro
|
||||||
|
|
||||||
Here's how you might begin:
|
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
|
: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
|
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>.
|
<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.
|
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
|
:marked
|
||||||
### The _myUnless_ property
|
### The _myUnless_ property
|
||||||
|
|
||||||
The directive consumer expects to bind a true/false condition to `[myUnless]`.
|
The directive consumer expects to bind a true/false condition to `[myUnless]`.
|
||||||
That means the directive needs a `myUnless` property, decorated with `@Input`
|
That means the directive needs a `myUnless` property, decorated with `@Input`
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
Read about `@Input` in the [_Template Syntax_](template-syntax.html#inputs-outputs) guide.
|
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
|
:marked
|
||||||
Angular sets the `myUnless` property whenever the value of the condition changes.
|
Angular sets the `myUnless` property whenever the value of the condition changes.
|
||||||
Because the `myUnless` property does work, it needs a setter.
|
Because the `myUnless` property does work, it needs a setter.
|
||||||
|
@ -532,16 +563,19 @@ block unless-intro
|
||||||
|
|
||||||
The completed directive code looks like this:
|
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
|
:marked
|
||||||
Add this directive to the `!{_declsVsDirectives}` !{_array} of the !{_AppModuleVsAppComp}.
|
Add this directive to the `!{_declsVsDirectives}` !{_array} of the !{_AppModuleVsAppComp}.
|
||||||
|
|
||||||
Then create some HTML to try it.
|
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
|
:marked
|
||||||
When the `condition` is falsy, the top (A) paragraph appears and the bottom (B) paragraph disappears.
|
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.
|
When the `condition` is truthy, the top (A) paragraph is removed and the bottom (B) paragraph appears.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/structural-directives/unless-anim.gif' alt="UnlessDirective in action" )
|
img(src='/resources/images/devguide/structural-directives/unless-anim.gif' alt="UnlessDirective in action" )
|
||||||
|
|
||||||
|
@ -551,7 +585,7 @@ a#summary
|
||||||
## Summary
|
## Summary
|
||||||
You can both try and download the source code for this guide in the <live-example></live-example>.
|
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(`
|
+makeTabs(`
|
||||||
structural-directives/ts/src/app/app.component.ts,
|
structural-directives/ts/src/app/app.component.ts,
|
||||||
|
@ -574,9 +608,10 @@ a#summary
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
You learned
|
You learned
|
||||||
|
|
||||||
* that structural directives manipulate HTML layout.
|
* that structural directives manipulate HTML layout.
|
||||||
* to use [`<ng-container>`](#ngcontainer) as a grouping element when there is no suitable host element.
|
* 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.
|
* how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives.
|
||||||
* about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template).
|
* about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template).
|
||||||
* to write a [custom structural directive](#unless), `UnlessDirective`.
|
* to write a [custom structural directive](#unless), `UnlessDirective`.
|
||||||
|
|
Loading…
Reference in New Issue