https://github.com/angular/angular
Tip revision: a16e3b8fe1f77b163b0763c263d98f275a6c038c authored by Dylan Hunn on 27 September 2023, 20:21:49 UTC
release: cut the v16.2.7 release
release: cut the v16.2.7 release
Tip revision: a16e3b8
app.component.html
<!-- #docplaster -->
<!-- #docregion -->
<h1><ng-container></h1>
<div *ngIf="hero">{{hero.name}}</div>
<hr>
<h3><ng-container> and CSS</h3>
<p>Examples demonstrating issues with rigid CSS styles.</p>
<button type="button" (click)="hero = hero ? null : heroes[0]">Toggle hero</button>
<h4>#1 <ng-container> and <p></h4>
<p>
I turned the corner
<ng-container *ngIf="hero">
and saw {{hero.name}}. I waved
</ng-container>
and continued on my way.
</p>
<p>
I turned the corner
<span *ngIf="hero">
and saw {{hero.name}}. I waved
</span>
and continued on my way.
</p>
<h4>#2 <ng-container> and <p></h4>
<div *ngIf="hero">
<p>
{{hero.name}} is
<ng-container *ngFor="let trait of heroTraits; let first=first; let last=last">
<ng-container *ngIf="!first">,</ng-container>
<ng-container *ngIf="last">and</ng-container>
{{trait}}
</ng-container>.
</p>
<p>
{{hero.name}} is
<span *ngFor="let trait of heroTraits; let first=first; let last=last">
<span *ngIf="!first">,</span>
<span *ngIf="last">and</span>
{{trait}}
</span>.
</p>
<br>
<h4>#3 <ng-container> and <p></h4>
<p>
<label for="showId"><input id="showId" type="checkbox" [checked]="showId" (change)="showId=!showId">Show ID</label>
</p>
<div>
The <code>hero.id</code> in the <span>
is caught by the <span>p-span</span> CSS:
<p>
<span *ngIf="showId">
Id: ({{hero.id}})
</span>
Name: {{hero.name}}
</p>
</div>
<div>
The <code>hero.id</code> in the <ng-container>
is unaffected by the <span>p-span</span> CSS:
<p>
<ng-container *ngIf="showId">
Id: ({{hero.id}})
</ng-container>
Name: {{hero.name}}
</p>
</div>
<div>
The <code>hero.id</code> in the <ng-template *ngIf> disappears:
<p>
<ng-template *ngIf="showId">
Id: ({{hero.id}})
</ng-template>
Name: {{hero.name}}
</p>
</div>
<div>
The <code>hero.id</code> in the <ng-template [ngIf]>
is unaffected by the <span>p-span</span> CSS:
<p>
<ng-template [ngIf]="showId">
Id: ({{hero.id}})
</ng-template>
Name: {{hero.name}}
</p>
</div>
</div>
<hr>
<h3><ng-container> and layout-sensitive elements</h3>
<p>
Examples demonstrating issues with layout-sensitive elements
such as <select> and <table>.
</p>
<h4>#1 <ng-container> and <options></h4>
<p><em><select> with <span></em></p>
<div>
Pick your favorite hero
(<label for="favorite-hero">
<input id="favorite-hero" type="checkbox" checked (change)="showSad=!showSad">
show sad
</label>)
</div>
<select [(ngModel)]="hero">
<span *ngFor="let h of heroes">
<span *ngIf="showSad || h?.emotion !== 'sad'">
<option [ngValue]="h">{{h.name}} ({{h?.emotion}})</option>
</span>
</span>
</select>
<p><em><select> with <ng-container></em></p>
<div>
Pick your favorite hero
(<label for="show-sad"><input id="show-sad" type="checkbox" checked (change)="showSad=!showSad">show sad</label>)
</div>
<select [(ngModel)]="hero">
<ng-container *ngFor="let h of heroes">
<ng-container *ngIf="showSad || h?.emotion !== 'sad'">
<option [ngValue]="h">{{h.name}} ({{h?.emotion}})</option>
</ng-container>
</ng-container>
</select>
<br><br><br><br>
<h4>#2 <ng-container> and <options></h4>
<p>
<label for="default-traits" (change)="traitPicker.value=showDefaultTraits ? 'loyal' : heroTraits[0]">
<input id="default-traits" type="checkbox"
[checked]="showDefaultTraits"
(change)="showDefaultTraits=!showDefaultTraits">Show default traits
</label>
</p>
<p>Options with <ng-container></p>
<select #traitPicker>
<ng-container *ngIf="showDefaultTraits">
<!-- Default traits -->
<option value="loyal">LOYAL</option>
<option value="clean">CLEAN</option>
<option value="reverent">REVERENT</option>
</ng-container>
<option *ngFor="let trait of heroTraits" [value]="trait">
{{ trait | uppercase }}
</option>
</select>
<p>Options with <span></p>
<select>
<!-- Default traits are always excluded because intermediate <span> is illegal -->
<span *ngIf="showDefaultTraits">
<option value="loyal">LOYAL</option>
<option value="clean">CLEAN</option>
<option value="reverent">REVERENT</option>
</span>
<option *ngFor="let trait of heroTraits" [value]="trait">
{{ trait | uppercase }}
</option>
</select>
<br>
<h4><ng-container> and <table></h4>
<p>
<label for="attrDirs">
<input id="attrDirs" type="checkbox" checked (change)="attrDirs=!attrDirs">
Attribute directives
</label>
<label for="strucDirs">
<input id="strucDirs" type="checkbox" checked (change)="strucDirs=!strucDirs">
Structural directives
</label>
<label for="divNgIf">
<input id="divNgIf" type="checkbox" (change)="divNgIf=!divNgIf">
div with *ngIf
</label>
</p>
<table>
<tr>
<th style="width:20%">Directive</th>
<th style="width:10%">Type</th>
<th>Description</th>
</tr>
<tr *ngIf="attrDirs">
<td>NgClass</td><td>A</td><td>Add or remove multiple CSS classes.</td>
</tr>
<ng-container *ngIf="divNgIf">
<div *ngIf="strucDirs">
<tr>
<td>xxx</td><td>S</td><td>div with *ngIf formats crazy.</td>
</tr>
<tr>
<td>yyy</td><td>S</td><td>div with *ngIf formats crazy.</td>
</tr>
</div>
</ng-container>
<ng-container *ngIf="strucDirs">
<tr>
<td>NgFor</td><td>S</td><td>Repeat the template for each item in a list.</td>
</tr>
<tr>
<td>NgIf</td><td>S</td><td>Add or remove DOM elements.</td>
</tr>
</ng-container>
<ng-container *ngIf="attrDirs">
<tr>
<td>NgStyle</td><td>A</td><td>Add or remove multiple style attributes.</td>
</tr>
</ng-container>
<tr *ngIf="strucDirs">
<td>NgSwitch</td><td>S</td><td>Include in DOM if case matches the switch value.</td>
</tr>
</table>
<hr>
<h3>Do not confuse <ng-container> with <ng-content></h3>
<p><ng-container>Inside ng-container</ng-container></p>
<ng-container>Inside ng-container</ng-container>
<p><ng-content>this is an Angular parse error</ng-content></p>
<!-- <ng-content>this is an Angular parse error</ng-content> -->
<div class="code">Template parse errors:<br>
<ng-content> element cannot have content.</div>
<p>Demo of </ng-content></p>
<content-comp>
Projected content
</content-comp>