@@ -27,15 +27,6 @@ style.
27
27
28
28
Try the <live-example></live-example>.
29
29
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
-
39
30
a#definition
40
31
.l-main-section
41
32
:marked
@@ -49,14 +40,16 @@ a#definition
49
40
The directive then does whatever it's supposed to do with that host element and its descendents.
50
41
51
42
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 .
53
44
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngif' )( format ="." )
54
45
: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.
57
47
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.
60
53
61
54
Three of the common, built-in structural directives—[NgIf](template-syntax.html#ngIf),
62
55
[NgFor](template-syntax.html#ngFor), and [NgSwitch...](template-syntax.html#ngSwitch)—are
@@ -68,6 +61,20 @@ a#definition
68
61
This guide won't repeat how to _use_ them. But it does explain _how they work_
69
62
and how to [write your own](#unless) structural directive.
70
63
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
+
71
78
.l-sub-section
72
79
:marked
73
80
There are two other kinds of Angular directives, described extensively elsewhere: (1) components and (2) attribute directives.
@@ -87,7 +94,6 @@ a#definition
87
94
You can [only apply one](#one-per-element) _structural_ directive to a host element.
88
95
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
89
96
90
-
91
97
a#ngIf
92
98
.l-main-section
93
99
:marked
@@ -149,8 +155,8 @@ figure.image-display
149
155
and recover the unused resources with a structural directive like `NgIf` .
150
156
151
157
**These same considerations apply to every structural directive, whether built-in or custom.**
152
- We should ask ourselves—and the users of our directives— 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.
154
160
155
161
a#ngcontainer
156
162
a#ng-container
@@ -296,7 +302,7 @@ a#ngfor
296
302
Angular transforms the `*ngFor` in similar fashion from asterisk (\*) syntax through
297
303
template _attribute_ to template _element_.
298
304
299
- Here's a full-featured `ngFor `, written all three ways:
305
+ Here's a full-featured application of `NgFor `, written all three ways:
300
306
+ makeExample('structural-directives/ts/app/app.component.html' , 'inside-ngfor' )( format ="." )
301
307
302
308
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
@@ -306,7 +312,7 @@ a#ngfor
306
312
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
307
313
:marked
308
314
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.
310
316
At minimum `NgFor` needs a looping variable (`let hero`) and a list (`heroes`).
311
317
312
318
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](microsyntax).
@@ -325,35 +331,39 @@ a#microsyntax
325
331
326
332
* The `let` keyword declares a [_template input variable_](#template-input-variable)
327
333
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 ,
329
335
`let-hero`, `let-i`, and `let-odd`.
330
336
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`.
334
341
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`.
338
344
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.
350
347
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
351
354
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
352
355
+ makeExample('structural-directives/ts/src/app/structural-directives.component.html' , 'ngSwitch' )( format ="." )
353
356
= ======
354
357
You can leverage the microsyntax in your own structural directive, should you decide to write one as
355
358
complex as `NgFor`.
356
359
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
357
367
358
368
359
369
a#template-input-variable
@@ -419,30 +429,40 @@ a#ngswitch
419
429
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngswitch' )( format ="." )
420
430
421
431
:marked
432
+ The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
433
+ (if any) of the switch cases are displayed.
434
+
422
435
`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 .
424
437
That's why you write `[ngSwitch]`, never `*ngSwitch`.
425
438
439
+ <<<<<<< 35892422d3f2027422c5387d51a5ce59bf54798e
426
440
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
427
441
+ makeExample('structural-directives/ts/src/app/structural-directives.component.html' , 'ngIf-template' )( format ="." )
428
442
= ======
429
443
`NgSwitchCase` and `NgSwitchDefault` are structural directives and are written with the asterisk (\*) prefix.
430
444
`NgSwitchCase` includes its host element when its value matches the `NgSwitch` value.
431
445
`NgSwitchDefault` includes its host element when no `NgSwitchCase` does.
432
446
>>>>>>> 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
433
453
434
- .alert.is-critical
454
+ .l-sub-section
435
455
: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`.
439
459
440
460
:marked
441
461
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
442
462
can be "de-sugared" into the template _attribute_ form.
443
463
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngswitch-template-attr' )( format ="." )
444
464
:marked
445
- The `<template>` element form is verbose .
465
+ That, in turn, can be "de-sugared" into the `<template>` element form.
446
466
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngswitch-template' )( format ="." )
447
467
448
468
a#prefer-asterisk
@@ -523,15 +543,16 @@ block unless-intro
523
543
+ makeExample('structural-directives/ts/app/my-unless.directive.ts' , 'skeleton' , 'my-unless.directive.ts (skeleton)' )( format ="." )
524
544
525
545
: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]`.
527
547
The brackets define a CSS
528
548
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors" target="_blank" title="MDN: Attribute selectors">attribute selector</a>.
529
549
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.
531
551
Don't use `ng`. That prefix belongs to Angular.
532
552
Pick something short that fits you or your company.
533
553
In this example, the prefix is `my`.
534
554
555
+ <<<<<<< 35892422d3f2027422c5387d51a5ce59bf54798e
535
556
<<<<<<< a5705eb367d80adf19abf765d735b9d1189b52e6
536
557
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
537
558
+ makeExample('structural-directives/ts/src/app/unless.directive.ts' , 'unless-constructor' )( format ="." )
@@ -542,6 +563,8 @@ block unless-intro
542
563
Ward: Why is this called a *key* when it looks like the value in a
543
564
key value pair?^^
544
565
566
+ = ======
567
+ >>>>>>> docs(structural-directive): answer K's questions for W
545
568
:marked
546
569
>>>>>>> docs(template-syntax/structural-directives): Add edits and comments on structural-directives
547
570
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
580
603
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
581
604
582
605
: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
585
607
608
+ <<<<<<< 35892422d3f2027422c5387d51a5ce59bf54798e
586
609
<<<<<<< a5705eb367d80adf19abf765d735b9d1189b52e6
587
610
<<<<<<< dc4da634c40560e4eda55814676bc96a230428dc
588
611
+ makeExample('structural-directives/ts/src/app/structural-directives.component.html' , 'myUnless' )( format ="." )
589
612
= ======
590
613
= ======
591
614
.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
592
620
: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.
604
622
605
623
>>>>>>> docs(template-syntax/structural-directives): Add edits and comments on structural-directives
606
624
+ makeExample('structural-directives/ts/app/my-unless.directive.ts' , 'set' )( format ="." )
607
625
>>>>>>> docs(template-syntax/structural-directives): refresh both guides for style, accuracy, understanding
608
626
: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.
610
629
611
630
* 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.
613
632
614
633
* If the condition is truthy and the view is currently displayed,
615
634
clear the container which also destroys the view.
616
635
636
+ Nobody reads the `myUnless` property so it doesn't need a getter.
637
+
617
638
The completed directive code looks like this:
618
639
619
640
+ makeExample('structural-directives/ts/app/my-unless.directive.ts' , 'no-docs' , 'my-unless.directive.ts' )
0 commit comments