@@ -27,6 +27,15 @@ 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
+
30
39
a#definition
31
40
.l-main-section
32
41
:marked
@@ -49,9 +58,10 @@ a#definition
49
58
You'll learn in this guide that the [asterisk (\*) is a convenience syntax](#asterisk). Angular "de-sugars" it into a `<template>` around the
50
59
host element and its descendents. Each structural directive does something different with that template.
51
60
52
- Three of the common, built-in structural directives —
53
- [NgIf](template-syntax.html#ngIf), [NgFor](template-syntax.html#ngFor), and [NgSwitch...](template-syntax.html#ngSwitch) —
54
- are described in the [_Template Syntax_](template-syntax.html) guide and seen in samples throughout the Angular documentation.
61
+ Three of the common, built-in structural directives—[NgIf](template-syntax.html#ngIf),
62
+ [NgFor](template-syntax.html#ngFor), and [NgSwitch...](template-syntax.html#ngSwitch)—are
63
+ described in the [_Template Syntax_](template-syntax.html) guide and seen in samples throughout the Angular documentation.
64
+ Here's an example of them in a template:
55
65
56
66
+ makeExample('structural-directives/ts/app/app.component.html' , 'built-in' )( format ="." )
57
67
:marked
80
90
## NgIf Case Study
81
91
82
92
`NgIf` is the simplest structural directive and the easiest to understand.
83
- It takes a boolean value and makes an entire chunk of DOM appear or disappear.
93
+ It takes a boolean value and makes an entire chunk of the DOM appear or disappear.
84
94
85
95
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngif-true' )( format ="." )
86
96
@@ -95,9 +105,9 @@ figure.image-display
95
105
The top paragraph is in the DOM. The bottom, disused paragraph is not;
96
106
in its place is a comment about "template bindings" (more about that [later](#asterisk)).
97
107
98
- When the condition is false, `NgIf` removes its host element from DOM,
99
- detaches it from DOM events (the attachments that it made)
100
- detaches the component from Angular change detection and destroys it.
108
+ When the condition is false, `NgIf` removes its host element from the DOM,
109
+ detaches it from DOM events (the attachments that it made),
110
+ detaches the component from Angular change detection, and destroys it.
101
111
The component and DOM nodes can be garbage-collected and free up memory.
102
112
103
113
### Why *remove* rather than *hide*?
@@ -118,20 +128,20 @@ figure.image-display
118
128
Angular keeps checking for changes that could affect data bindings.
119
129
Whatever the component was doing, it keeps doing.
120
130
121
- Although invisible, the component — and all of its descendant components — tie up resources.
131
+ Although invisible, the component—and all of its descendant components—tie up resources.
122
132
The performance and memory burden can be substantial, responsiveness can degrade, and the user sees nothing.
123
133
124
134
On the positive side, showing the element again is quick.
125
135
The component's previous state is preserved and ready to display.
126
- The component doesn't re-initialize — an operation that could be expensive.
136
+ The component doesn't re-initialize—an operation that could be expensive.
127
137
So hiding and showing is sometimes the right thing to do.
128
138
129
139
But in the absence of a compelling reason to keep them around,
130
140
your preference should be to remove DOM elements that the user can't see
131
141
and recover the unused resources with a structural directive like `NgIf` .
132
142
133
143
**These same considerations apply to every structural directive, whether built-in or custom.**
134
- We should ask ourselves — and the users of our directives — to think carefully
144
+ We should ask ourselves—and the users of our directives—to think carefully
135
145
about the consequences of adding and removing elements and of creating and destroying components.
136
146
137
147
a#ngcontainer
@@ -152,16 +162,16 @@ a#ng-container
152
162
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngif' )( format ="." )
153
163
154
164
:marked
155
- Introducing another container element — typically a `<span>` or `<div>` —
156
- to group the elements under a single _root_ is usually harmless.
165
+ Introducing another container element—typically a `<span>` or `<div>`—to
166
+ group the elements under a single _root_ is usually harmless.
157
167
_Usually_ ... but not _always_.
158
168
159
169
The grouping element may break the template appearance because CSS styles
160
170
neither expect nor accommodate the new layout.
161
171
For example, suppose you have the following paragraph layout.
162
172
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngif-span' )( format ="." )
163
173
:marked
164
- You also have a CSS style rule that happens to apply to a `<span>` within `<p>`aragraph.
174
+ You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
165
175
+ makeExample('structural-directives/ts/app/app.component.css' , 'p-span' )( format ="." )
166
176
:marked
167
177
The constructed paragraph renders strangely.
@@ -270,12 +280,12 @@ a#ngfor
270
280
Angular transforms the `*ngFor` in similar fashion from asterisk (\*) syntax through
271
281
template _attribute_ to template _element_.
272
282
273
- Here's a full-featured `ngFor`, written all three ways
283
+ Here's a full-featured `ngFor`, written all three ways:
274
284
+ makeExample('structural-directives/ts/app/app.component.html' , 'inside-ngfor' )( format ="." )
275
285
276
286
:marked
277
287
This is manifestly more complicated than `ngIf` and rightly so.
278
- `NgFor ` directive has more features, both required and optional, than the `NgIf` shown in this guide.
288
+ The `ngFor ` directive has more features, both required and optional, than the `NgIf` shown in this guide.
279
289
At minimum `NgFor` needs a looping variable (`let hero`) and a list (`heroes`).
280
290
281
291
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](microsyntax).
@@ -305,6 +315,14 @@ a#microsyntax
305
315
The `NgFor` directive sets its _context's_ `$implicit` property to the current item in the list during each iteration.
306
316
That becomes the current value of the `hero` variable in the example above.
307
317
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
308
326
* The other _let_ variables (`i` and `odd`) are linked to one of the directive's _named context_ properties.
309
327
Look to the directive's documentation to see which properties are available and what they do.
310
328
`NgFor` has several, including `index` and `odd`.
@@ -360,7 +378,7 @@ a#ngswitch
360
378
:marked
361
379
## Inside the _NgSwitch_ directives
362
380
363
- The Angular _NgSwitch_ is actally a set of cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault`.
381
+ The Angular _NgSwitch_ is actually a set of cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault`.
364
382
365
383
Here's an example.
366
384
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngswitch' )( format ="." )
@@ -374,6 +392,13 @@ a#ngswitch
374
392
`NgSwitchCase` includes its host element when its value matches the `NgSwitch` value.
375
393
`NgSwitchDefault` includes its host element when no `NgSwitchCase` does.
376
394
395
+ .alert.is-critical
396
+ :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?
400
+
401
+ :marked
377
402
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
378
403
can be "de-sugared" into the template _attribute_ form.
379
404
+ makeExample('structural-directives/ts/app/app.component.html' , 'ngswitch-template-attr' )( format ="." )
@@ -422,7 +447,7 @@ a#unless
422
447
## Write a structural directive
423
448
In this section, you write a `MyUnless` directive structural directive
424
449
that does the opposite of `NgIf`.
425
- `NgIf` displays the template content when the condition `true`.
450
+ `NgIf` displays the template content when the condition is `true`.
426
451
`MyUnless` displays the content when the condition is ***false***.
427
452
428
453
+ makeExample('structural-directives/ts/app/app.component.html' , 'myUnless-1' )( format ="." )
@@ -454,6 +479,12 @@ block unless-intro
454
479
Pick something short that fits you or your company.
455
480
In this example, the prefix is `my`.
456
481
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
+
487
+ :marked
457
488
The directive _class_ name ends in `Directive` per the [style guide](style-guide.html#02-03 "Angular Style Guide").
458
489
Angular's own directives do not.
459
490
@@ -478,12 +509,26 @@ block unless-intro
478
509
The directive consumer expects to bind a condition to a directive property's `myUnless` input property.
479
510
Add the `@Input() myUnless` input property as a setter-only (there's no need to read it).
480
511
512
+ .alert.is-critical
513
+ :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.
525
+
481
526
+ makeExample('structural-directives/ts/app/my-unless.directive.ts' , 'set' )( format ="." )
482
527
:marked
483
528
Angular calls this setter whenever the value of the condition changes.
484
529
485
530
* If the condition is falsy and the view hasn't been created previously,
486
- let the create the _view container_ create the _embedded view_ from the template.
531
+ let the _view container_ create the _embedded view_ from the template.
487
532
488
533
* If the condition is truthy and the view is currently displayed,
489
534
clear the container which also destroys the view.
@@ -534,7 +579,7 @@ a#summary
534
579
You learned
535
580
* that structural directives manipulate HTML layout.
536
581
* to use [`<ng-container>`](#ngcontainer) as a grouping element when there is no suitable host element.
537
- * that the angular "de-sugars" [asterisk (\*) syntax](#asterisk) into a `<template>`
538
- * how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives
539
- * about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template)
582
+ * that the angular "de-sugars" [asterisk (\*) syntax](#asterisk) into a `<template>`.
583
+ * how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives.
584
+ * about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template).
540
585
* to write a [custom structural directive](#unless), `myUnless`.
0 commit comments