Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 5a2703f

Browse files
committed
docs(structural-directive): answer K's questions for W
1 parent 2ee183c commit 5a2703f

File tree

1 file changed

+69
-72
lines changed

1 file changed

+69
-72
lines changed

public/docs/ts/latest/guide/structural-directives.jade

Lines changed: 69 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,6 @@ style.
2727

2828
Try the <live-example></live-example>.
2929

30-
.alert.is-helpful
31-
:marked
32-
`NgFor` and `ngFor` appear throughout the Angular documentation
33-
and you may wonder what the difference is. The _directive_ name is `NgFor`.
34-
Its _usage in a template_ is `ngFor`. This is critical in
35-
differentiating between the *context* of the directive or
36-
a *property* of the directive. `NgFor` has a `NgForTrackBy`
37-
property. The attribute `ngFor` doesn't have any properties.
38-
3930
a#definition
4031
.l-main-section
4132
:marked
@@ -49,14 +40,16 @@ a#definition
4940
The directive then does whatever it's supposed to do with that host element and its descendents.
5041

5142
Structural directives are easy to recognize.
52-
An asterisk (\*) precedes the directive selector name which is set to a string.
43+
An asterisk (\*) precedes the directive attribute name as in this example.
5344
+makeExample('structural-directives/ts/app/app.component.html', 'ngif')(format=".")
5445
:marked
55-
No brackets. No parentheses. Just a string, which is either a [template expression](template-syntax.html#template-expressions)
56-
or a [microsyntax](#microsyntax).
46+
No brackets. No parentheses. Just `*ngIf` set to a string.
5747

58-
You'll learn in this guide that the [asterisk (\*) is a convenience syntax](#asterisk). Angular "de-sugars" it into a `<template>` around the
59-
host element and its descendents. Each structural directive does something different with that template.
48+
You'll learn in this guide that the [asterisk (\*) is a convenience notation](#asterisk)
49+
and the string is a [_microsyntax_](#microsyntax) rather than the usual [template expression](template-syntax.html#template-expressions).
50+
Angular "de-sugars" this notation into a marked-up `<template>` that surrounds the
51+
host element and its descendents.
52+
Each structural directive does something different with that template.
6053

6154
Three of the common, built-in structural directives&mdash;[NgIf](template-syntax.html#ngIf),
6255
[NgFor](template-syntax.html#ngFor), and [NgSwitch...](template-syntax.html#ngSwitch)&mdash;are
@@ -68,6 +61,20 @@ a#definition
6861
This guide won't repeat how to _use_ them. But it does explain _how they work_
6962
and how to [write your own](#unless) structural directive.
7063

64+
.callout.is-helpful
65+
header Directive spelling
66+
:marked
67+
Throughout this guide, you'll see a directive spelled in both _UpperCamelCase_ and _lowerCamelCase_.
68+
Already you've seen `NgIf` and `ngIf`.
69+
There's a reason. `NgIf` refers to the directive _class_;
70+
`ngIf` refers to the directive's _attribute name_.
71+
72+
A directive _class_ is spelled in _UpperCamelCase_ (`NgIf`).
73+
A directive's _attribute name_ is spelled in _lowerCamelCase_ (`ngIf`).
74+
The guide refers to the directive _class_ when talking about its properties and what the directive does.
75+
The guide refers to the _attribute name_ when describing how
76+
you apply the directive to an element in the HTML template.
77+
7178
.l-sub-section
7279
:marked
7380
There are two other kinds of Angular directives, described extensively elsewhere: (1)&nbsp;components and (2)&nbsp;attribute directives.
@@ -83,7 +90,6 @@ a#definition
8390
You can apply many _attribute_ directives to one host element.
8491
You can [only apply one](#one-per-element) _structural_ directive to a host element.
8592

86-
8793
a#ngIf
8894
.l-main-section
8995
:marked
@@ -141,8 +147,8 @@ figure.image-display
141147
and recover the unused resources with a structural directive like `NgIf` .
142148

143149
**These same considerations apply to every structural directive, whether built-in or custom.**
144-
We should ask ourselves&mdash;and the users of our directives&mdash;to think carefully
145-
about the consequences of adding and removing elements and of creating and destroying components.
150+
Before applying a structural directive, you might want to pause for a moment
151+
to consider the consequences of adding and removing elements and of creating and destroying components.
146152

147153
a#ngcontainer
148154
a#ng-container
@@ -280,12 +286,12 @@ a#ngfor
280286
Angular transforms the `*ngFor` in similar fashion from asterisk (\*) syntax through
281287
template _attribute_ to template _element_.
282288

283-
Here's a full-featured `ngFor`, written all three ways:
289+
Here's a full-featured application of `NgFor`, written all three ways:
284290
+makeExample('structural-directives/ts/app/app.component.html', 'inside-ngfor')(format=".")
285291

286292
:marked
287293
This is manifestly more complicated than `ngIf` and rightly so.
288-
The `ngFor` directive has more features, both required and optional, than the `NgIf` shown in this guide.
294+
The `NgFor` directive has more features, both required and optional, than the `NgIf` shown in this guide.
289295
At minimum `NgFor` needs a looping variable (`let hero`) and a list (`heroes`).
290296

291297
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](microsyntax).
@@ -304,32 +310,30 @@ a#microsyntax
304310

305311
* The `let` keyword declares a [_template input variable_](#template-input-variable)
306312
that you reference within the template. The input variables in this example are `hero`, `i`, and `odd`.
307-
The parser translates `let hero`, `let i`, and `let odd` into the declaration tokens,
313+
The parser translates `let hero`, `let i`, and `let odd` into variables named,
308314
`let-hero`, `let-i`, and `let-odd`.
309315

310-
* The `of` and `trackby` translate to the `ngForOf` and `ngForTrackBy` _input properties_ of the `NgFor` directive.
311-
The parser creates these directive property names by title-casing the name-fragment (`of` -> `Of`, `trackBy` -> `TrackBy`) and
312-
and prefixing it with the directive key (`ngFor`).
316+
* The microsyntax parser takes `of` and `trackby`, title-cases them (`of` -> `Of`, `trackBy` -> `TrackBy`),
317+
and prefixes them with the directive's attribute name (`ngFor`), yielding the names `ngForOf` and `ngForTrackBy`.
318+
Those are the names of two `NgFor` _input properties_ .
319+
That's how the directive learns that the list is `heroes` and the track-by function is `trackById`.
313320

314-
* The one unassigned _let_ variable (`hero`) is tied to the directive _context's_ `$implicit` property.
315-
The `NgFor` directive sets its _context's_ `$implicit` property to the current item in the list during each iteration.
316-
That becomes the current value of the `hero` variable in the example above.
321+
* As the `NgFor` directive loops through the list, it sets and resets properties of its own _context_ object.
322+
These properties include `index` and `odd` and a special property named `$implicit`.
317323

318-
.alert.is-critical
319-
:marked
320-
Ward: I got lost on this third point. ^^ By context, do we mean the element that the
321-
directive is on, such as the `<div>`? Next, I was thrown by `$implicit`. What is that?
322-
Obviously a property, but why the `$` and should I know more about properties of
323-
contexts? Can we link to something for more info? I felt like this was touching
324-
on deep stuff.
325-
:marked
326-
* The other _let_ variables (`i` and `odd`) are linked to one of the directive's _named context_ properties.
327-
Look to the directive's documentation to see which properties are available and what they do.
328-
`NgFor` has several, including `index` and `odd`.
324+
* The `let-i` and `let-odd` variables were defined as `let i=index` and `let odd=odd`.
325+
Angular sets them to the current value of the context's `index` and `odd` properties.
326+
327+
* The context property for `let-hero` wasn't specified.
328+
It's intended source is implicit.
329+
Angular sets `let-hero` to the value of the context's `$implicit` property
330+
which `NgFor` has initialized with the hero for the current iteration.
329331

330-
You can leverage the microsyntax in your own structural directive, should you decide to write one as
331-
complex as `NgFor`.
332-
Studying the source code for `NgFor` is the best way to learn.
332+
* The [API guide](../api/common/index/NgFor-directive.html "API: NgFor")
333+
describes additional `NgFor` directive properties and context properties.
334+
335+
These microsyntax mechanisms are available to you when you write your own structural directives.
336+
Studying the source code for `NgIf` and `NgFor` is a great way to learn more.
333337

334338

335339
a#template-input-variable
@@ -384,26 +388,30 @@ a#ngswitch
384388
+makeExample('structural-directives/ts/app/app.component.html', 'ngswitch')(format=".")
385389

386390
:marked
391+
The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
392+
(if any) of the switch cases are displayed.
393+
387394
`NgSwitch` itself is not a structural directive.
388-
It's an _attribute_ directive that controls the behavior of the `NgSwitchCase` and `NgSwitchDefault`.
395+
It's an _attribute_ directive that controls the behavior of the other two switch directives.
389396
That's why you write `[ngSwitch]`, never `*ngSwitch`.
390397

391-
`NgSwitchCase` and `NgSwitchDefault` are structural directives and are written with the asterisk (\*) prefix.
392-
`NgSwitchCase` includes its host element when its value matches the `NgSwitch` value.
393-
`NgSwitchDefault` includes its host element when no `NgSwitchCase` does.
398+
`NgSwitchCase` and `NgSwitchDefault` _are_ structural directives.
399+
You attach them to elements using the asterisk (\*) prefix notation.
400+
An `NgSwitchCase` displays its host element when its value matches the switch value.
401+
The `NgSwitchDefault` displays its host element when no sibling `NgSwitchCase` matches the switch value.
394402

395-
.alert.is-critical
403+
.l-sub-section
396404
:marked
397-
Ward: I was following along until these last two sentences above ^^. What does
398-
"includes its host element" mean? Possibly in the same way we mean when we say
399-
that something is in an include?
405+
The element to which you apply a directive is its _host_ element.
406+
The `<happy-hero>` is the host element for the happy `*ngSwitchCase`.
407+
The `<unknown-hero>` is the host element for the `*ngSwitchDefault`.
400408

401409
:marked
402410
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
403411
can be "de-sugared" into the template _attribute_ form.
404412
+makeExample('structural-directives/ts/app/app.component.html', 'ngswitch-template-attr')(format=".")
405413
:marked
406-
The `<template>` element form is verbose.
414+
That, in turn, can be "de-sugared" into the `<template>` element form.
407415
+makeExample('structural-directives/ts/app/app.component.html', 'ngswitch-template')(format=".")
408416

409417
a#prefer-asterisk
@@ -470,20 +478,15 @@ block unless-intro
470478
+makeExample('structural-directives/ts/app/my-unless.directive.ts', 'skeleton', 'my-unless.directive.ts (skeleton)')(format=".")
471479

472480
:marked
473-
The directive's _selector_ is typically the directive's **key** in square brackets.`[myUnless]`.
481+
The directive's _selector_ is typically the directive's **attribute name** in square brackets.`[myUnless]`.
474482
The brackets define a CSS
475483
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors" target="_blank" title="MDN: Attribute selectors">attribute selector</a>.
476484

477-
The directive _key_ should be spelled in _lowerCamelCase_ and begin with a prefix.
485+
The directive _attribute name_ should be spelled in _lowerCamelCase_ and begin with a prefix.
478486
Don't use `ng`. That prefix belongs to Angular.
479487
Pick something short that fits you or your company.
480488
In this example, the prefix is `my`.
481489

482-
.alert.is-critical
483-
:marked
484-
Ward: Why is this called a *key* when it looks like the value in a
485-
key value pair?^^
486-
487490
:marked
488491
The directive _class_ name ends in `Directive` per the [style guide](style-guide.html#02-03 "Angular Style Guide").
489492
Angular's own directives do not.
@@ -506,33 +509,27 @@ block unless-intro
506509
+makeExample('structural-directives/ts/app/my-unless.directive.ts', 'ctor')(format=".")
507510

508511
:marked
509-
The directive consumer expects to bind a condition to a directive property's `myUnless` input property.
510-
Add the `@Input() myUnless` input property as a setter-only (there's no need to read it).
512+
### The _myUnless_ property
511513

512-
.alert.is-critical
514+
The directive consumer expects to bind a true/false condition to `[myUnless]`.
515+
That means the directive needs a `myUnless` property, decorated with `@Input`
516+
.l-sub-section
513517
:marked
514-
Ward: This first sentence threw me at first. I had to read it several times. I
515-
understand until the phrase "directive property's `myUnless` input property". I get
516-
"`myUnless` input property", since you just showed it, but I don't understand
517-
the relationship between the directive property...and the `@Input`? I don't
518-
know if I'm wording that correctly.
519-
520-
For the snippet below, if I were following along to build my own, I'd have only a
521-
general notion of what was being specified in it and think to mysef "ok, I'm going to
522-
trust you on this one" and scroll down to hopefully find an example of it in action.
523-
The translation below helps but thought you should know I'd feel a little in need of
524-
bravery at first glance.
518+
Read about `@Input` in the [_Template Syntax_](template-syntax.html#inputs-outputs) guide.
525519

526520
+makeExample('structural-directives/ts/app/my-unless.directive.ts', 'set')(format=".")
527521
:marked
528-
Angular calls this setter whenever the value of the condition changes.
522+
Angular sets the `myUnless` property whenever the value of the condition changes.
523+
Because the `myUnless` property does work, it needs a setter.
529524

530525
* If the condition is falsy and the view hasn't been created previously,
531-
let the _view container_ create the _embedded view_ from the template.
526+
tell the _view container_ to create the _embedded view_ from the template.
532527

533528
* If the condition is truthy and the view is currently displayed,
534529
clear the container which also destroys the view.
535530

531+
Nobody reads the `myUnless` property so it doesn't need a getter.
532+
536533
The completed directive code looks like this:
537534

538535
+makeExample('structural-directives/ts/app/my-unless.directive.ts', 'no-docs', 'my-unless.directive.ts')

0 commit comments

Comments
 (0)