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

Commit dc52c5e

Browse files
committed
docs(structural-directive): answer K's questions for W
1 parent 3589242 commit dc52c5e

File tree

1 file changed

+81
-60
lines changed

1 file changed

+81
-60
lines changed

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

Lines changed: 81 additions & 60 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.
@@ -87,7 +94,6 @@ a#definition
8794
You can [only apply one](#one-per-element) _structural_ directive to a host element.
8895
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
8996

90-
9197
a#ngIf
9298
.l-main-section
9399
:marked
@@ -149,8 +155,8 @@ figure.image-display
149155
and recover the unused resources with a structural directive like `NgIf` .
150156

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

155161
a#ngcontainer
156162
a#ng-container
@@ -296,7 +302,7 @@ a#ngfor
296302
Angular transforms the `*ngFor` in similar fashion from asterisk (\*) syntax through
297303
template _attribute_ to template _element_.
298304

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

302308
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
@@ -306,7 +312,7 @@ a#ngfor
306312
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
307313
:marked
308314
This is manifestly more complicated than `ngIf` and rightly so.
309-
The `ngFor` directive has more features, both required and optional, than the `NgIf` shown in this guide.
315+
The `NgFor` directive has more features, both required and optional, than the `NgIf` shown in this guide.
310316
At minimum `NgFor` needs a looping variable (`let hero`) and a list (`heroes`).
311317

312318
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](microsyntax).
@@ -325,35 +331,39 @@ a#microsyntax
325331

326332
* The `let` keyword declares a [_template input variable_](#template-input-variable)
327333
that you reference within the template. The input variables in this example are `hero`, `i`, and `odd`.
328-
The parser translates `let hero`, `let i`, and `let odd` into the declaration tokens,
334+
The parser translates `let hero`, `let i`, and `let odd` into variables named,
329335
`let-hero`, `let-i`, and `let-odd`.
330336

331-
* The `of` and `trackby` translate to the `ngForOf` and `ngForTrackBy` _input properties_ of the `NgFor` directive.
332-
The parser creates these directive property names by title-casing the name-fragment (`of` -> `Of`, `trackBy` -> `TrackBy`) and
333-
and prefixing it with the directive key (`ngFor`).
337+
* The microsyntax parser takes `of` and `trackby`, title-cases them (`of` -> `Of`, `trackBy` -> `TrackBy`),
338+
and prefixes them with the directive's attribute name (`ngFor`), yielding the names `ngForOf` and `ngForTrackBy`.
339+
Those are the names of two `NgFor` _input properties_ .
340+
That's how the directive learns that the list is `heroes` and the track-by function is `trackById`.
334341

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

339-
.alert.is-critical
340-
:marked
341-
Ward: I got lost on this third point. ^^ By context, do we mean the element that the
342-
directive is on, such as the `<div>`? Next, I was thrown by `$implicit`. What is that?
343-
Obviously a property, but why the `$` and should I know more about properties of
344-
contexts? Can we link to something for more info? I felt like this was touching
345-
on deep stuff.
346-
:marked
347-
* The other _let_ variables (`i` and `odd`) are linked to one of the directive's _named context_ properties.
348-
Look to the directive's documentation to see which properties are available and what they do.
349-
`NgFor` has several, including `index` and `odd`.
345+
* The `let-i` and `let-odd` variables were defined as `let i=index` and `let odd=odd`.
346+
Angular sets them to the current value of the context's `index` and `odd` properties.
350347

348+
* The context property for `let-hero` wasn't specified.
349+
It's intended source is implicit.
350+
Angular sets `let-hero` to the value of the context's `$implicit` property
351+
which `NgFor` has initialized with the hero for the current iteration.
352+
353+
<<<<<<< 35892422d3f2027422c5387d51a5ce59bf54798e
351354
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
352355
+makeExample('structural-directives/ts/src/app/structural-directives.component.html', 'ngSwitch')(format=".")
353356
=======
354357
You can leverage the microsyntax in your own structural directive, should you decide to write one as
355358
complex as `NgFor`.
356359
Studying the source code for `NgFor` is the best way to learn.
360+
=======
361+
* The [API guide](../api/common/index/NgFor-directive.html "API: NgFor")
362+
describes additional `NgFor` directive properties and context properties.
363+
364+
These microsyntax mechanisms are available to you when you write your own structural directives.
365+
Studying the source code for `NgIf` and `NgFor` is a great way to learn more.
366+
>>>>>>> docs(structural-directive): answer K's questions for W
357367

358368

359369
a#template-input-variable
@@ -419,30 +429,40 @@ a#ngswitch
419429
+makeExample('structural-directives/ts/app/app.component.html', 'ngswitch')(format=".")
420430

421431
:marked
432+
The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
433+
(if any) of the switch cases are displayed.
434+
422435
`NgSwitch` itself is not a structural directive.
423-
It's an _attribute_ directive that controls the behavior of the `NgSwitchCase` and `NgSwitchDefault`.
436+
It's an _attribute_ directive that controls the behavior of the other two switch directives.
424437
That's why you write `[ngSwitch]`, never `*ngSwitch`.
425438

439+
<<<<<<< 35892422d3f2027422c5387d51a5ce59bf54798e
426440
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
427441
+makeExample('structural-directives/ts/src/app/structural-directives.component.html', 'ngIf-template')(format=".")
428442
=======
429443
`NgSwitchCase` and `NgSwitchDefault` are structural directives and are written with the asterisk (\*) prefix.
430444
`NgSwitchCase` includes its host element when its value matches the `NgSwitch` value.
431445
`NgSwitchDefault` includes its host element when no `NgSwitchCase` does.
432446
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
447+
=======
448+
`NgSwitchCase` and `NgSwitchDefault` _are_ structural directives.
449+
You attach them to elements using the asterisk (\*) prefix notation.
450+
An `NgSwitchCase` displays its host element when its value matches the switch value.
451+
The `NgSwitchDefault` displays its host element when no sibling `NgSwitchCase` matches the switch value.
452+
>>>>>>> docs(structural-directive): answer K's questions for W
433453

434-
.alert.is-critical
454+
.l-sub-section
435455
:marked
436-
Ward: I was following along until these last two sentences above ^^. What does
437-
"includes its host element" mean? Possibly in the same way we mean when we say
438-
that something is in an include?
456+
The element to which you apply a directive is its _host_ element.
457+
The `<happy-hero>` is the host element for the happy `*ngSwitchCase`.
458+
The `<unknown-hero>` is the host element for the `*ngSwitchDefault`.
439459

440460
:marked
441461
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
442462
can be "de-sugared" into the template _attribute_ form.
443463
+makeExample('structural-directives/ts/app/app.component.html', 'ngswitch-template-attr')(format=".")
444464
:marked
445-
The `<template>` element form is verbose.
465+
That, in turn, can be "de-sugared" into the `<template>` element form.
446466
+makeExample('structural-directives/ts/app/app.component.html', 'ngswitch-template')(format=".")
447467

448468
a#prefer-asterisk
@@ -523,15 +543,16 @@ block unless-intro
523543
+makeExample('structural-directives/ts/app/my-unless.directive.ts', 'skeleton', 'my-unless.directive.ts (skeleton)')(format=".")
524544

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

530-
The directive _key_ should be spelled in _lowerCamelCase_ and begin with a prefix.
550+
The directive _attribute name_ should be spelled in _lowerCamelCase_ and begin with a prefix.
531551
Don't use `ng`. That prefix belongs to Angular.
532552
Pick something short that fits you or your company.
533553
In this example, the prefix is `my`.
534554

555+
<<<<<<< 35892422d3f2027422c5387d51a5ce59bf54798e
535556
<<<<<<< a5705eb367d80adf19abf765d735b9d1189b52e6
536557
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
537558
+makeExample('structural-directives/ts/src/app/unless.directive.ts', 'unless-constructor')(format=".")
@@ -542,6 +563,8 @@ block unless-intro
542563
Ward: Why is this called a *key* when it looks like the value in a
543564
key value pair?^^
544565

566+
=======
567+
>>>>>>> docs(structural-directive): answer K's questions for W
545568
:marked
546569
>>>>>>> docs(template-syntax/structural-directives): Add edits and comments on structural-directives
547570
The directive _class_ name ends in `Directive` per the [style guide](style-guide.html#02-03 "Angular Style Guide").
@@ -580,40 +603,38 @@ block unless-intro
580603
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
581604

582605
:marked
583-
The directive consumer expects to bind a condition to a directive property's `myUnless` input property.
584-
Add the `@Input() myUnless` input property as a setter-only (there's no need to read it).
606+
### The _myUnless_ property
585607

608+
<<<<<<< 35892422d3f2027422c5387d51a5ce59bf54798e
586609
<<<<<<< a5705eb367d80adf19abf765d735b9d1189b52e6
587610
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
588611
+makeExample('structural-directives/ts/src/app/structural-directives.component.html', 'myUnless')(format=".")
589612
=======
590613
=======
591614
.alert.is-critical
615+
=======
616+
The directive consumer expects to bind a true/false condition to `[myUnless]`.
617+
That means the directive needs a `myUnless` property, decorated with `@Input`
618+
.l-sub-section
619+
>>>>>>> docs(structural-directive): answer K's questions for W
592620
:marked
593-
Ward: This first sentence threw me at first. I had to read it several times. I
594-
understand until the phrase "directive property's `myUnless` input property". I get
595-
"`myUnless` input property", since you just showed it, but I don't understand
596-
the relationship between the directive property...and the `@Input`? I don't
597-
know if I'm wording that correctly.
598-
599-
For the snippet below, if I were following along to build my own, I'd have only a
600-
general notion of what was being specified in it and think to mysef "ok, I'm going to
601-
trust you on this one" and scroll down to hopefully find an example of it in action.
602-
The translation below helps but thought you should know I'd feel a little in need of
603-
bravery at first glance.
621+
Read about `@Input` in the [_Template Syntax_](template-syntax.html#inputs-outputs) guide.
604622

605623
>>>>>>> docs(template-syntax/structural-directives): Add edits and comments on structural-directives
606624
+makeExample('structural-directives/ts/app/my-unless.directive.ts', 'set')(format=".")
607625
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
608626
:marked
609-
Angular calls this setter whenever the value of the condition changes.
627+
Angular sets the `myUnless` property whenever the value of the condition changes.
628+
Because the `myUnless` property does work, it needs a setter.
610629

611630
* If the condition is falsy and the view hasn't been created previously,
612-
let the _view container_ create the _embedded view_ from the template.
631+
tell the _view container_ to create the _embedded view_ from the template.
613632

614633
* If the condition is truthy and the view is currently displayed,
615634
clear the container which also destroys the view.
616635

636+
Nobody reads the `myUnless` property so it doesn't need a getter.
637+
617638
The completed directive code looks like this:
618639

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

0 commit comments

Comments
 (0)