14
14
15
15
- [What are structural directives?](#definition)
16
16
- [*NgIf* case study](#ngIf)
17
- - [Group sibling elements with <ng-container>](#ng-container)
18
17
- [The asterisk (*) prefix](#asterisk)
19
18
- [Inside *NgFor*](#ngFor)
20
19
- [microsyntax](#microsyntax)
23
22
- [Inside the *NgSwitch* directives](#ngSwitch)
24
23
- [Prefer the (*) prefix](#prefer-asterisk)
25
24
- [The <template> element](#template)
25
+ - [Group sibling elements with <ng-container>](#ng-container)
26
26
- [Write a structural directive](#unless)
27
27
28
28
Try the <live-example></live-example>.
@@ -157,108 +157,6 @@ figure.image-display
157
157
Before applying a structural directive, you might want to pause for a moment
158
158
to consider the consequences of adding and removing elements and of creating and destroying components.
159
159
160
- a#ngcontainer
161
- a#ng-container
162
- .l-main-section
163
- :marked
164
- ## Group sibling elements with <ng-container>
165
-
166
- There's often a _root_ element that can and should host the structural directive.
167
- The list element (`<li>`) is a typical host element of an `NgFor` repeater.
168
-
169
- + makeExcerpt('src/app/app.component.html' , 'ngfor-li' , '' )
170
-
171
- :marked
172
- When there isn't a host element, you can usually wrap the content in a native HTML container element,
173
- such as a `<div>`, and attach the directive to that wrapper.
174
-
175
- + makeExcerpt('src/app/app.component.html' , 'ngif' , '' )
176
-
177
- :marked
178
- Introducing another container element—typically a `<span>` or `<div>`—to
179
- group the elements under a single _root_ is usually harmless.
180
- _Usually_ ... but not _always_.
181
-
182
- The grouping element may break the template appearance because CSS styles
183
- neither expect nor accommodate the new layout.
184
- For example, suppose you have the following paragraph layout.
185
-
186
- + makeExcerpt('src/app/app.component.html' , 'ngif-span' , '' )
187
-
188
- :marked
189
- You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
190
-
191
- + makeExcerpt('src/app/app.component.css' , 'p-span' , '' )
192
-
193
- :marked
194
- The constructed paragraph renders strangely.
195
-
196
- figure.image-display
197
- img( src ='/resources/images/devguide/structural-directives/bad-paragraph.png' alt ="spanned paragraph with bad style" )
198
-
199
- :marked
200
- The `p span` style, intended for use elsewhere, was inadvertently applied here.
201
-
202
- Another problem: some HTML elements require all immediate children to be of a specific type.
203
- For example, the `<select>` element requires `<option>` children.
204
- You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
205
-
206
- When you try this,
207
-
208
- + makeExcerpt('src/app/app.component.html' , 'select-span' , '' )
209
-
210
- :marked
211
- the drop down is empty.
212
-
213
- figure.image-display
214
- img( src ='/resources/images/devguide/structural-directives/bad-select.png' alt ="spanned options don't work" )
215
-
216
- :marked
217
- The browser won't display an `<option>` within a `<span>`.
218
-
219
- ### <ng-container> to the rescue
220
-
221
- The Angular `<ng-container>` is a grouping element that doesn't interfere with styles or layout
222
- because Angular _doesn't put it in the DOM_.
223
-
224
- Here's the conditional paragraph again, this time using `<ng-container>`.
225
-
226
- + makeExcerpt('src/app/app.component.html' , 'ngif-ngcontainer' , '' )
227
-
228
- :marked
229
- It renders properly.
230
-
231
- figure.image-display
232
- img( src ='/resources/images/devguide/structural-directives/good-paragraph.png' alt ="ngcontainer paragraph with proper style" )
233
-
234
- :marked
235
- Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
236
-
237
- + makeExcerpt('src/app/app.component.html' , 'select-ngcontainer' , '' )
238
-
239
- :marked
240
- The drop down works properly.
241
-
242
- figure.image-display
243
- img( src ='/resources/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt ="ngcontainer options work properly" )
244
-
245
- :marked
246
- The `<ng-container>` is a syntax element recognized by the Angular parser.
247
- It's not a directive, component, class, or interface.
248
- It's more like the curly braces in a JavaScript `if`-block:
249
-
250
- code-example( language ="javascript" ) .
251
- if (someCondition) {
252
- statement1;
253
- statement2;
254
- statement3;
255
- }
256
-
257
- :marked
258
- Without those braces, JavaScript would only execute the first statement
259
- when you intend to conditionally execute all of them as a single block.
260
- The `<ng-container>` satisfies a similar need in Angular templates.
261
-
262
160
a#asterisk
263
161
.l-main-section
264
162
:marked
@@ -273,7 +171,7 @@ a#asterisk
273
171
274
172
:marked
275
173
The asterisk is "syntactic sugar" for something a bit more complicated.
276
- Internally, Angular " desugars" it in two stages.
174
+ Internally, Angular desugars it in two stages.
277
175
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`, like this.
278
176
279
177
+ makeExcerpt('src/app/app.component.html' , 'ngif-template-attr' , '' )
@@ -299,7 +197,7 @@ figure.image-display
299
197
300
198
The [`NgFor`](#ngFor) and [`NgSwitch...`](#ngSwitch) directives follow the same pattern.
301
199
302
- a#ngfor
200
+ a#ngFor
303
201
.l-main-section
304
202
:marked
305
203
## Inside _*ngFor_
@@ -400,7 +298,7 @@ a#one-per-element
400
298
There's an easy solution for this use case: put the `*ngIf` on a container element that wraps the `*ngFor` element.
401
299
One or both elements can be an [`ng-container`](#ngcontainer) so you don't have to introduce extra levels of HTML.
402
300
403
- a#ngswitch
301
+ a#ngSwitch
404
302
.l-main-section
405
303
:marked
406
304
## Inside _NgSwitch_ directives
@@ -477,7 +375,109 @@ figure.image-display
477
375
478
376
:marked
479
377
A structural directive puts a `<template>` to work
480
- as you'll see when you write your own structural directive.
378
+ as you'll see when you [write your own structural directive](#unless).
379
+
380
+ a#ngcontainer
381
+ a#ng-container
382
+ .l-main-section
383
+ :marked
384
+ ## Group sibling elements with <ng-container>
385
+
386
+ There's often a _root_ element that can and should host the structural directive.
387
+ The list element (`<li>`) is a typical host element of an `NgFor` repeater.
388
+
389
+ + makeExcerpt('src/app/app.component.html' , 'ngfor-li' , '' )
390
+
391
+ :marked
392
+ When there isn't a host element, you can usually wrap the content in a native HTML container element,
393
+ such as a `<div>`, and attach the directive to that wrapper.
394
+
395
+ + makeExcerpt('src/app/app.component.html' , 'ngif' , '' )
396
+
397
+ :marked
398
+ Introducing another container element—typically a `<span>` or `<div>`—to
399
+ group the elements under a single _root_ is usually harmless.
400
+ _Usually_ ... but not _always_.
401
+
402
+ The grouping element may break the template appearance because CSS styles
403
+ neither expect nor accommodate the new layout.
404
+ For example, suppose you have the following paragraph layout.
405
+
406
+ + makeExcerpt('src/app/app.component.html' , 'ngif-span' , '' )
407
+
408
+ :marked
409
+ You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
410
+
411
+ + makeExcerpt('src/app/app.component.css' , 'p-span' , '' )
412
+
413
+ :marked
414
+ The constructed paragraph renders strangely.
415
+
416
+ figure.image-display
417
+ img( src ='/resources/images/devguide/structural-directives/bad-paragraph.png' alt ="spanned paragraph with bad style" )
418
+
419
+ :marked
420
+ The `p span` style, intended for use elsewhere, was inadvertently applied here.
421
+
422
+ Another problem: some HTML elements require all immediate children to be of a specific type.
423
+ For example, the `<select>` element requires `<option>` children.
424
+ You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
425
+
426
+ When you try this,
427
+
428
+ + makeExcerpt('src/app/app.component.html' , 'select-span' , '' )
429
+
430
+ :marked
431
+ the drop down is empty.
432
+
433
+ figure.image-display
434
+ img( src ='/resources/images/devguide/structural-directives/bad-select.png' alt ="spanned options don't work" )
435
+
436
+ :marked
437
+ The browser won't display an `<option>` within a `<span>`.
438
+
439
+ ### <ng-container> to the rescue
440
+
441
+ The Angular `<ng-container>` is a grouping element that doesn't interfere with styles or layout
442
+ because Angular _doesn't put it in the DOM_.
443
+
444
+ Here's the conditional paragraph again, this time using `<ng-container>`.
445
+
446
+ + makeExcerpt('src/app/app.component.html' , 'ngif-ngcontainer' , '' )
447
+
448
+ :marked
449
+ It renders properly.
450
+
451
+ figure.image-display
452
+ img( src ='/resources/images/devguide/structural-directives/good-paragraph.png' alt ="ngcontainer paragraph with proper style" )
453
+
454
+ :marked
455
+ Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
456
+
457
+ + makeExcerpt('src/app/app.component.html' , 'select-ngcontainer' , '' )
458
+
459
+ :marked
460
+ The drop down works properly.
461
+
462
+ figure.image-display
463
+ img( src ='/resources/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt ="ngcontainer options work properly" )
464
+
465
+ :marked
466
+ The `<ng-container>` is a syntax element recognized by the Angular parser.
467
+ It's not a directive, component, class, or interface.
468
+ It's more like the curly braces in a JavaScript `if`-block:
469
+
470
+ code-example( language ="javascript" ) .
471
+ if (someCondition) {
472
+ statement1;
473
+ statement2;
474
+ statement3;
475
+ }
476
+
477
+ :marked
478
+ Without those braces, JavaScript would only execute the first statement
479
+ when you intend to conditionally execute all of them as a single block.
480
+ The `<ng-container>` satisfies a similar need in Angular templates.
481
481
482
482
a#unless
483
483
.l-main-section
@@ -583,6 +583,7 @@ a#summary
583
583
.l-main-section
584
584
:marked
585
585
## Summary
586
+
586
587
You can both try and download the source code for this guide in the <live-example></live-example>.
587
588
588
589
Here is the source from the `src/app/` folder.
@@ -611,7 +612,7 @@ a#summary
611
612
612
613
* that structural directives manipulate HTML layout.
613
614
* to use [`<ng-container>`](#ngcontainer) as a grouping element when there is no suitable host element.
614
- * that the Angular " desugars" [asterisk (*) syntax](#asterisk) into a `<template>`.
615
+ * that the Angular desugars [asterisk (*) syntax](#asterisk) into a `<template>`.
615
616
* how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives.
616
617
* about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template).
617
618
* to write a [custom structural directive](#unless), `UnlessDirective`.
0 commit comments