docs(template-syntax): add TOC, NgSwitch, and NgForTrackBy - TS/Dart
This commit is contained in:
parent
d4914eed26
commit
ee5a4e131a
|
@ -28,9 +28,6 @@ class AppComponent {
|
||||||
// String badCurly = 'bad curly'; // XXX: This isn't working.
|
// String badCurly = 'bad curly'; // XXX: This isn't working.
|
||||||
String badCurly = 'bad'; // XXX: This isn't working.
|
String badCurly = 'bad'; // XXX: This isn't working.
|
||||||
// List<String> badCurly = ['bad', 'curly']; // XXX: This isn't working.
|
// List<String> badCurly = ['bad', 'curly']; // XXX: This isn't working.
|
||||||
String title = 'Template Syntax';
|
|
||||||
String toeChoice;
|
|
||||||
int val = 2;
|
|
||||||
bool canSave = true;
|
bool canSave = true;
|
||||||
bool isActive = false;
|
bool isActive = false;
|
||||||
bool isSpecial = true;
|
bool isSpecial = true;
|
||||||
|
@ -143,6 +140,8 @@ class AppComponent {
|
||||||
}
|
}
|
||||||
// #enddocregion setStyles
|
// #enddocregion setStyles
|
||||||
|
|
||||||
|
String title = 'Template Syntax';
|
||||||
|
String toeChoice;
|
||||||
String toeChooser(Element picker) {
|
String toeChooser(Element picker) {
|
||||||
List<Element> choices = picker.children;
|
List<Element> choices = picker.children;
|
||||||
for (var i = 0; i < choices.length; i++) {
|
for (var i = 0; i < choices.length; i++) {
|
||||||
|
@ -153,4 +152,51 @@ class AppComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #docregion trackByHeroes
|
||||||
|
int trackByHeroes(int index, Hero hero) { return hero.id; }
|
||||||
|
// #enddocregion trackByHeroes
|
||||||
|
|
||||||
|
// #docregion trackById
|
||||||
|
int trackById(int index, Map item): string { return item['id']; }
|
||||||
|
// #enddocregion trackById
|
||||||
|
|
||||||
|
int val = 2;
|
||||||
|
|
||||||
|
|
||||||
|
//////// Detect effects of NgForTrackBy ///////////////
|
||||||
|
int heroesNoTrackByChangeCount = 0;
|
||||||
|
int heroesWithTrackByChangeCount = 0;
|
||||||
|
/*
|
||||||
|
// Convert to Dart
|
||||||
|
@ViewChildren('noTrackBy') childrenNoTrackBy:QueryList<ElementRef>;
|
||||||
|
@ViewChildren('withTrackBy') childrenWithTrackBy:QueryList<ElementRef>;
|
||||||
|
|
||||||
|
private _oldNoTrackBy:HTMLElement[];
|
||||||
|
private _oldWithTrackBy:HTMLElement[];
|
||||||
|
|
||||||
|
private _detectNgForTrackByEffects() {
|
||||||
|
this._oldNoTrackBy = toArray(this.childrenNoTrackBy);
|
||||||
|
this._oldWithTrackBy = toArray(this.childrenWithTrackBy);
|
||||||
|
|
||||||
|
this.childrenNoTrackBy.changes.subscribe((changes:any) => {
|
||||||
|
let newNoTrackBy = toArray(changes);
|
||||||
|
let isSame = this._oldNoTrackBy.every((v:any, i:number) => v === newNoTrackBy[i]);
|
||||||
|
if (!isSame) {
|
||||||
|
this._oldNoTrackBy = newNoTrackBy;
|
||||||
|
this.heroesNoTrackByChangeCount++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.childrenWithTrackBy.changes.subscribe((changes:any) => {
|
||||||
|
let newWithTrackBy = toArray(changes);
|
||||||
|
let isSame = this._oldWithTrackBy.every((v:any, i:number) => v === newWithTrackBy[i]);
|
||||||
|
if (!isSame) {
|
||||||
|
this._oldWithTrackBy = newWithTrackBy;
|
||||||
|
this.heroesWithTrackByChangeCount++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
///////////////////
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,44 @@
|
||||||
<!-- #docregion my-first-app -->
|
<!-- #docplaster -->
|
||||||
<h3>My First Angular Application</h3>
|
<a id="toc"></a>
|
||||||
<!-- #enddocregion my-first-app -->
|
<h1>Template Syntax</h1>
|
||||||
|
<a href="#interpolation">Interpolation</a><br>
|
||||||
|
<a href="#mental-model">Mental Model</a><br>
|
||||||
|
<a href="#buttons">Buttons</a><br>
|
||||||
|
<a href="#prop-vs-attrib">Properties vs. Attributes</a><br>
|
||||||
|
<br>
|
||||||
|
<a href="#property-binding">Property Binding</a><br>
|
||||||
|
<div style="margin-left:8px">
|
||||||
|
<a href="#attribute-binding">Attribute Binding</a><br>
|
||||||
|
<a href="#class-binding">Class Binding</a><br>
|
||||||
|
<a href="#style-binding">Style Binding</a><br>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<a href="#event-binding">Event Binding</a><br>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<div>Directives</div>
|
||||||
|
<div style="margin-left:8px">
|
||||||
|
<a href="#ngModel">NgModel (two-way) Binding</a><br>
|
||||||
|
<a href="#ngClass">NgClass Binding</a><br>
|
||||||
|
<a href="#ngStyle">NgStyle Binding</a><br>
|
||||||
|
<a href="#ngIf">NgIf</a><br>
|
||||||
|
<a href="#ngSwitch">NgSwitch</a><br>
|
||||||
|
<a href="#ngFor">NgFor</a><br>
|
||||||
|
<div style="margin-left:8px">
|
||||||
|
<a href="#ngFor-index">NgFor with index</a><br>
|
||||||
|
<a href="#ngFor-trackBy">NgFor with trackBy</a><br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<a href="#star-prefix">* prefix and <template></a><br>
|
||||||
|
<a href="#local-vars">Template local variables</a><br>
|
||||||
|
<a href="#inputs-and-outputs">Inputs and outputs</a><br>
|
||||||
|
<a href="#pipes">Pipes</a><br>
|
||||||
|
<a href="#elvis">Elvis <i>?.</i></a><br>
|
||||||
|
<!--<a href="#enums">Enums</a><br>-->
|
||||||
|
|
||||||
<!-- Interpolation and expressions -->
|
<!-- Interpolation and expressions -->
|
||||||
<hr><h2>Interpolation</h2>
|
<hr><h2 id="interpolation">Interpolation</h2>
|
||||||
|
|
||||||
<!-- #docregion first-interpolation -->
|
<!-- #docregion first-interpolation -->
|
||||||
<p>My current hero is {{currentHero.firstName}}</p>
|
<p>My current hero is {{currentHero.firstName}}</p>
|
||||||
|
@ -26,9 +61,10 @@
|
||||||
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}</p>
|
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}</p>
|
||||||
<!-- #enddocregion sum-2 -->
|
<!-- #enddocregion sum-2 -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- New Mental Model -->
|
<!-- New Mental Model -->
|
||||||
<hr><h2>New Mental Model</h2>
|
<hr><h2 id="mental-model">New Mental Model</h2>
|
||||||
|
|
||||||
<!--<img src="http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png">-->
|
<!--<img src="http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png">-->
|
||||||
<!-- Public Domain terms of use: http://www.wpclipart.com/terms.html -->
|
<!-- Public Domain terms of use: http://www.wpclipart.com/terms.html -->
|
||||||
|
@ -65,11 +101,10 @@
|
||||||
</div>
|
</div>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<!-- See https://github.com/angular/angular/issues/5707 about "myClick (myClick)" -->
|
|
||||||
<!-- #docregion event-binding-syntax-1 -->
|
<!-- #docregion event-binding-syntax-1 -->
|
||||||
<button (click) = "onSave()">Save</button>
|
<button (click) = "onSave()">Save</button>
|
||||||
<hero-detail (deleted)="onHeroDeleted()"></hero-detail>
|
<hero-detail (deleted)="onHeroDeleted()"></hero-detail>
|
||||||
<div myClick (myClick)="clickity=$event">click me</div>
|
<div (myClick)="clickity=$event">click me</div>
|
||||||
<!-- #enddocregion event-binding-syntax-1 -->
|
<!-- #enddocregion event-binding-syntax-1 -->
|
||||||
{{clickity}}
|
{{clickity}}
|
||||||
<br><br>
|
<br><br>
|
||||||
|
@ -97,8 +132,10 @@
|
||||||
<!-- #enddocregion style-binding-syntax-1 -->
|
<!-- #enddocregion style-binding-syntax-1 -->
|
||||||
button</button>
|
button</button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- property vs. attribute -->
|
<!-- property vs. attribute -->
|
||||||
<hr><h2>Property vs. Attribute (img examples)</h2>
|
<hr><h2 id="prop-vs-attrib">Property vs. Attribute (img examples)</h2>
|
||||||
<!-- examine the following <img> tag in the browser tools -->
|
<!-- examine the following <img> tag in the browser tools -->
|
||||||
<img src="assets/images/ng-logo.png"
|
<img src="assets/images/ng-logo.png"
|
||||||
[src]="heroImageUrl">
|
[src]="heroImageUrl">
|
||||||
|
@ -109,10 +146,10 @@ button</button>
|
||||||
<img bind-src="heroImageUrl"/>
|
<img bind-src="heroImageUrl"/>
|
||||||
<img [attr.src]="villainImageUrl"/>
|
<img [attr.src]="villainImageUrl"/>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- buttons -->
|
<!-- buttons -->
|
||||||
<hr><h2>Buttons</h2>
|
<hr><h2 id="buttons">Buttons</h2>
|
||||||
|
|
||||||
<button>Enabled (but does nothing)</button>
|
<button>Enabled (but does nothing)</button>
|
||||||
<button disabled>Disabled</button>
|
<button disabled>Disabled</button>
|
||||||
|
@ -124,9 +161,10 @@ button</button>
|
||||||
<button bind-disabled="isUnchanged" on-click="onSave($event)">Disabled Cancel</button>
|
<button bind-disabled="isUnchanged" on-click="onSave($event)">Disabled Cancel</button>
|
||||||
<button [disabled]="!canSave" (click)="onSave($event)">Enabled Save</button>
|
<button [disabled]="!canSave" (click)="onSave($event)">Enabled Save</button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- property binding -->
|
<!-- property binding -->
|
||||||
<hr><h2>Property Binding</h2>
|
<hr><h2 id="property-binding">Property Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion property-binding-1 -->
|
<!-- #docregion property-binding-1 -->
|
||||||
<img [src]="heroImageUrl">
|
<img [src]="heroImageUrl">
|
||||||
|
@ -159,8 +197,10 @@ button</button>
|
||||||
<div [textContent]="'The title is ' + title"></div>
|
<div [textContent]="'The title is ' + title"></div>
|
||||||
<!-- #enddocregion property-binding-vs-interpolation -->
|
<!-- #enddocregion property-binding-vs-interpolation -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- attribute binding -->
|
<!-- attribute binding -->
|
||||||
<hr><h2>Attribute Binding</h2>
|
<hr><h2 id="attribute-binding">Attribute Binding</h2>
|
||||||
|
|
||||||
<!-- create and set a colspan attribute -->
|
<!-- create and set a colspan attribute -->
|
||||||
<!-- #docregion attrib-binding-colspan -->
|
<!-- #docregion attrib-binding-colspan -->
|
||||||
|
@ -197,12 +237,10 @@ button</button>
|
||||||
<button disabled [disabled]="false">Enabled (but inert)</button>
|
<button disabled [disabled]="false">Enabled (but inert)</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- class binding -->
|
<!-- class binding -->
|
||||||
<hr><h2>Class Binding</h2>
|
<hr><h2 id="class-binding">Class Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion class-binding-1 -->
|
<!-- #docregion class-binding-1 -->
|
||||||
<!-- standard class attribute setting -->
|
<!-- standard class attribute setting -->
|
||||||
|
@ -229,10 +267,10 @@ button</button>
|
||||||
|
|
||||||
<div bind-class.special="isSpecial">This class binding is special too</div>
|
<div bind-class.special="isSpecial">This class binding is special too</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!--style binding -->
|
<!--style binding -->
|
||||||
<hr><h2>Style Binding</h2>
|
<hr><h2 id="style-binding">Style Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion style-binding-1 -->
|
<!-- #docregion style-binding-1 -->
|
||||||
<button [style.color] = "isSpecial ? 'red': 'green'">Red</button>
|
<button [style.color] = "isSpecial ? 'red': 'green'">Red</button>
|
||||||
|
@ -244,8 +282,10 @@ button</button>
|
||||||
<button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>
|
<button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>
|
||||||
<!-- #enddocregion style-binding-2 -->
|
<!-- #enddocregion style-binding-2 -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- event binding -->
|
<!-- event binding -->
|
||||||
<hr><h2>Event Binding</h2>
|
<hr><h2 id="event-binding">Event Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion event-binding-1 -->
|
<!-- #docregion event-binding-1 -->
|
||||||
<button (click)="onSave()">Save</button>
|
<button (click)="onSave()">Save</button>
|
||||||
|
@ -260,7 +300,7 @@ button</button>
|
||||||
<!-- `myClick` is an event on the custom `MyClickDirective` -->
|
<!-- `myClick` is an event on the custom `MyClickDirective` -->
|
||||||
|
|
||||||
<!-- #docregion my-click -->
|
<!-- #docregion my-click -->
|
||||||
<div myClick (myClick)="clickMessage=$event">click with myClick</div>
|
<div (myClick)="clickMessage=$event">click with myClick</div>
|
||||||
<!-- #enddocregion my-click -->
|
<!-- #enddocregion my-click -->
|
||||||
<!-- #enddocregion event-binding-3 -->
|
<!-- #enddocregion event-binding-3 -->
|
||||||
{{clickMessage}}
|
{{clickMessage}}
|
||||||
|
@ -301,10 +341,11 @@ button</button>
|
||||||
<!-- #enddocregion event-binding-propagation -->
|
<!-- #enddocregion event-binding-propagation -->
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- Two way data binding unwound;
|
<!-- Two way data binding unwound;
|
||||||
passing the changed display value to the event handler via `$event` -->
|
passing the changed display value to the event handler via `$event` -->
|
||||||
<hr><h2>NgModel Binding</h2>
|
<hr><h2 id="ngModel">NgModel (two-way) Binding</h2>
|
||||||
|
|
||||||
<h3>Result: {{currentHero.firstName}}</h3>
|
<h3>Result: {{currentHero.firstName}}</h3>
|
||||||
|
|
||||||
|
@ -339,10 +380,10 @@ bindon-ngModel
|
||||||
(ngModelChange) = "setUpperCaseFirstName($event)"
|
(ngModelChange) = "setUpperCaseFirstName($event)"
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgClass binding -->
|
<!-- NgClass binding -->
|
||||||
<hr><h2>NgClass Binding</h2>
|
<hr><h2 id="ngClass">NgClass Binding</h2>
|
||||||
|
|
||||||
<p>setClasses returns {{setClasses() | json}}</p>
|
<p>setClasses returns {{setClasses() | json}}</p>
|
||||||
<!-- #docregion NgClass-1 -->
|
<!-- #docregion NgClass-1 -->
|
||||||
|
@ -359,6 +400,7 @@ bindon-ngModel
|
||||||
<div class="bad curly special">Bad curly special</div>
|
<div class="bad curly special">Bad curly special</div>
|
||||||
<div [ngClass]="{bad:false, curly:true, special:true}">Curly special</div>
|
<div [ngClass]="{bad:false, curly:true, special:true}">Curly special</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgStyle binding -->
|
<!-- NgStyle binding -->
|
||||||
<hr><h2>NgStyle Binding</h2>
|
<hr><h2>NgStyle Binding</h2>
|
||||||
|
@ -384,10 +426,10 @@ bindon-ngModel
|
||||||
|
|
||||||
<!-- not used in chapter -->
|
<!-- not used in chapter -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgIf binding -->
|
<!-- NgIf binding -->
|
||||||
<hr><h2>NgIf Binding</h2>
|
<hr><h2 id="ngIf">NgIf Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion NgIf-1 -->
|
<!-- #docregion NgIf-1 -->
|
||||||
<div *ngIf="currentHero != null">Hello, {{currentHero.firstName}}</div>
|
<div *ngIf="currentHero != null">Hello, {{currentHero.firstName}}</div>
|
||||||
|
@ -402,7 +444,6 @@ bindon-ngModel
|
||||||
<hero-detail *ngIf="isActive"></hero-detail>
|
<hero-detail *ngIf="isActive"></hero-detail>
|
||||||
<!-- #enddocregion NgIf-2 -->
|
<!-- #enddocregion NgIf-2 -->
|
||||||
|
|
||||||
|
|
||||||
<!-- NgIf binding with template (no *) -->
|
<!-- NgIf binding with template (no *) -->
|
||||||
|
|
||||||
<template [ngIf]="currentHero != null">Add {{currentHero.firstName}} with template</template>
|
<template [ngIf]="currentHero != null">Add {{currentHero.firstName}} with template</template>
|
||||||
|
@ -425,10 +466,10 @@ bindon-ngModel
|
||||||
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
||||||
<!-- #enddocregion NgIf-3 -->
|
<!-- #enddocregion NgIf-3 -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgSwitch binding -->
|
<!-- NgSwitch binding -->
|
||||||
<hr><h2>NgSwitch Binding</h2>
|
<hr><h2 id="ngSwitch">NgSwitch Binding</h2>
|
||||||
|
|
||||||
<fieldset #toePicker (click)="toeChooser(toePicker)" >
|
<fieldset #toePicker (click)="toeChooser(toePicker)" >
|
||||||
<input type="radio" name="toes" value="Eenie">Eenie
|
<input type="radio" name="toes" value="Eenie">Eenie
|
||||||
|
@ -439,23 +480,39 @@ bindon-ngModel
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="toe">
|
<div class="toe">
|
||||||
<div *ngIf="toeChoice == null">Pick a toe</div>
|
<div *ngIf="toeChoice == null">Pick a toe</div>
|
||||||
<div *ngIf="toeChoice != null">You picked
|
<div *ngIf="toeChoice != null">
|
||||||
<!-- #docregion NgSwitch -->
|
You picked ...
|
||||||
<span [ngSwitch]="toeChoice">
|
<!-- #docregion NgSwitch, NgSwitch-expanded -->
|
||||||
<template [ngSwitchWhen]="'Eenie'">Eenie</template>
|
<span [ngSwitch]="toeChoice">
|
||||||
<template [ngSwitchWhen]="'Meanie'">Meanie</template>
|
<!-- #enddocregion NgSwitch -->
|
||||||
<template [ngSwitchWhen]="'Miney'">Miney</template>
|
|
||||||
<template [ngSwitchWhen]="'Moe'">Moe</template>
|
|
||||||
<template ngSwitchDefault>Other</template>
|
|
||||||
</span>
|
|
||||||
<!-- #enddocregion NgSwitch -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<!-- with *NgSwitch -->
|
||||||
|
<!-- #docregion NgSwitch -->
|
||||||
|
<span *ngSwitchWhen="'Eenie'">Eenie</span>
|
||||||
|
<span *ngSwitchWhen="'Meanie'">Meanie</span>
|
||||||
|
<span *ngSwitchWhen="'Miney'">Miney</span>
|
||||||
|
<span *ngSwitchWhen="'Moe'">Moe</span>
|
||||||
|
<span *ngSwitchDefault>other</span>
|
||||||
|
<!-- #enddocregion NgSwitch -->
|
||||||
|
|
||||||
|
<!-- with <template> -->
|
||||||
|
<template [ngSwitchWhen]="'Eenie'"><span>Eenie</span></template>
|
||||||
|
<template [ngSwitchWhen]="'Meanie'"><span>Meanie</span></template>
|
||||||
|
<template [ngSwitchWhen]="'Miney'"><span>Miney</span></template>
|
||||||
|
<template [ngSwitchWhen]="'Moe'"><span>Moe</span></template>
|
||||||
|
<template ngSwitchDefault><span>other</span></template>
|
||||||
|
|
||||||
|
<!-- #docregion NgSwitch -->
|
||||||
|
</span>
|
||||||
|
<!-- #enddocregion NgSwitch, NgSwitch-expanded -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgFor binding -->
|
<!-- NgFor binding -->
|
||||||
<hr><h2>NgFor Binding</h2>
|
<hr><h2 id="ngFor">NgFor Binding</h2>
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- #docregion NgFor-1 -->
|
<!-- #docregion NgFor-1 -->
|
||||||
|
@ -470,52 +527,126 @@ bindon-ngModel
|
||||||
<hero-detail *ngFor="#hero of heroes" [hero]="hero"></hero-detail>
|
<hero-detail *ngFor="#hero of heroes" [hero]="hero"></hero-detail>
|
||||||
<!-- #enddocregion NgFor-2 -->
|
<!-- #enddocregion NgFor-2 -->
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
|
<h4 id="ngFor-index">NgFor with index</h4>
|
||||||
|
<p>with <i>semi-colon</i> separator</p>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- Ex: 1 - Hercules Son of Zeus -->
|
|
||||||
<!-- #docregion NgFor-3 -->
|
<!-- #docregion NgFor-3 -->
|
||||||
<div *ngFor="#hero of heroes, #i=index">{{i + 1}} - {{hero.fullName}}</div>
|
<div *ngFor="#hero of heroes; #i=index">{{i + 1}} - {{hero.fullName}}</div>
|
||||||
<!-- #enddocregion NgFor-3 -->
|
<!-- #enddocregion NgFor-3 -->
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
|
<p>with <i>comma</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- Ex: "1 - Hercules Son of Zeus"" -->
|
||||||
|
<div *ngFor="#hero of heroes, #i=index">{{i + 1}} - {{hero.fullName}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
|
<h4 id="ngFor-trackBy">NgForTrackBy</h4>
|
||||||
|
<button (click)="refreshHeroes()">Refresh heroes</button>
|
||||||
|
<p>First hero: <input [(ngModel)]="heroes[0].firstName"></p>
|
||||||
|
|
||||||
|
<p><i>without</i> trackBy</p>
|
||||||
|
<div #noTrackBy class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-1 -->
|
||||||
|
<div *ngFor="#hero of heroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-1 -->
|
||||||
|
</div>
|
||||||
|
<div id="noTrackByCnt" *ngIf="heroesNoTrackByChangeCount != 0" style="background-color:bisque">
|
||||||
|
Hero DOM elements change #<span style="background-color:gold">{{heroesNoTrackByChangeCount}}</span> without trackBy
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>semi-colon</i> separator</p>
|
||||||
|
<div #withTrackBy class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-2 -->
|
||||||
|
<div *ngFor="#hero of heroes; trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-2 -->
|
||||||
|
</div>
|
||||||
|
<div id="withTrackByCnt" *ngIf="heroesWithTrackByChangeCount != 0" style="background-color:bisque">
|
||||||
|
Hero DOM elements change #<span style="background-color:gold">{{heroesWithTrackByChangeCount}}</span> with trackBy
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>comma</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<div *ngFor="#hero of heroes, trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>space</i> separator</p>
|
||||||
|
<div #withTrackBy class="box">
|
||||||
|
<div *ngFor="#hero of heroes trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with <i>*ngForTrackBy</i></p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-2 -->
|
||||||
|
<div *ngFor="#hero of heroes" *ngForTrackBy="trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-2 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with <i>generic</i> trackById function</p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-3 -->
|
||||||
|
<div *ngFor="#hero of heroes" *ngForTrackBy="trackById">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-3 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- * and template -->
|
<!-- * and template -->
|
||||||
<hr><h2>* and Template</h2>
|
<hr><h2 id="star-prefix">* prefix and <template></h2>
|
||||||
|
|
||||||
<h3>NgIf expansion</h3>
|
<h3>*ngIf expansion</h3>
|
||||||
|
<p><i>*ngIf</i></p>
|
||||||
<!-- #docregion Template-1 -->
|
<!-- #docregion Template-1 -->
|
||||||
<hero-detail *ngIf="currentHero != null" [hero]="currentHero"></hero-detail>
|
<hero-detail *ngIf="currentHero != null" [hero]="currentHero"></hero-detail>
|
||||||
<!-- #enddocregion Template-1 -->
|
<!-- #enddocregion Template-1 -->
|
||||||
|
|
||||||
|
<p><i>expand to template = "..."</i></p>
|
||||||
|
<!-- #docregion Template-2a -->
|
||||||
|
<hero-detail template="ngIf:currentHero != null" [hero]="currentHero"></hero-detail>
|
||||||
|
<!-- #enddocregion Template-2a -->
|
||||||
|
|
||||||
|
<p><i>expand to <template></i></p>
|
||||||
<!-- #docregion Template-2 -->
|
<!-- #docregion Template-2 -->
|
||||||
<template [ngIf]="currentHero != null">
|
<template [ngIf]="currentHero != null">
|
||||||
<hero-detail [hero]="currentHero"></hero-detail>
|
<hero-detail [hero]="currentHero"></hero-detail>
|
||||||
</template>
|
</template>
|
||||||
<!-- #enddocregion Template-2 -->
|
<!-- #enddocregion Template-2 -->
|
||||||
|
|
||||||
<h3>NgFor expansion</h3>
|
<h3>*ngFor expansion</h3>
|
||||||
|
<p><i>*ngFor</i></p>
|
||||||
|
<!-- *ngFor w/ hero-detail Component -->
|
||||||
|
<!-- #docregion Template-3a -->
|
||||||
|
<hero-detail *ngFor="#hero of heroes; trackBy:trackByHeroes" [hero]="hero"></hero-detail>
|
||||||
|
<!-- #enddocregion Template-3a -->
|
||||||
|
|
||||||
|
<p><i>expand to template = "..."</i></p>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- ngFor w/ hero-detail Component and a template "attribute" directive -->
|
<!-- *ngFor w/ hero-detail Component and a template "attribute" directive -->
|
||||||
<!-- #docregion Template-3 -->
|
<!-- #docregion Template-3 -->
|
||||||
<hero-detail template="ngFor #hero of heroes" [hero]="hero"></hero-detail>
|
<hero-detail template="ngFor #hero of heroes; trackBy:trackByHeroes" [hero]="hero"></hero-detail>
|
||||||
<!-- #enddocregion Template-3 -->
|
<!-- #enddocregion Template-3 -->
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<p><i>expand to <template></i></p>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- ngFor w/ hero-detail Component inside a template element -->
|
<!-- ngFor w/ hero-detail Component inside a template element -->
|
||||||
<!-- #docregion Template-4 -->
|
<!-- #docregion Template-4 -->
|
||||||
<template ngFor #hero [ngForOf]="heroes">
|
<template ngFor #hero [ngForOf]="heroes" [ngForTrackBy]="trackByHeroes>
|
||||||
<hero-detail [hero]="hero"></hero-detail>
|
<hero-detail [hero]="hero"></hero-detail>
|
||||||
</template>
|
</template>
|
||||||
<!-- #enddocregion Template-4 -->
|
<!-- #enddocregion Template-4 -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- template local variable -->
|
<!-- template local variable -->
|
||||||
<hr><h2>Template local variables</h2>
|
<hr><h2 id="local-vars">Template local variables</h2>
|
||||||
|
|
||||||
<!-- #docregion var-phone -->
|
<!-- #docregion var-phone -->
|
||||||
<!-- phone refers to the input element; pass its `value` to an event handler -->
|
<!-- phone refers to the input element; pass its `value` to an event handler -->
|
||||||
|
@ -547,8 +678,10 @@ bindon-ngModel
|
||||||
<!-- btn refers to the button element; show its disabled state -->
|
<!-- btn refers to the button element; show its disabled state -->
|
||||||
<button #btn disabled [textContent]="'disabled by attribute: ' + btn.disabled.toString()"></button>
|
<button #btn disabled [textContent]="'disabled by attribute: ' + btn.disabled.toString()"></button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- inputs and output -->
|
<!-- inputs and output -->
|
||||||
<hr><h2>Inputs and Outputs</h2>
|
<hr><h2 id="inputs-and-outputs">Inputs and Outputs</h2>
|
||||||
|
|
||||||
<!-- #docregion io-1 -->
|
<!-- #docregion io-1 -->
|
||||||
<img [src]="iconUrl"/>
|
<img [src]="iconUrl"/>
|
||||||
|
@ -560,11 +693,13 @@ bindon-ngModel
|
||||||
</hero-detail>
|
</hero-detail>
|
||||||
<!-- #enddocregion io-2 -->
|
<!-- #enddocregion io-2 -->
|
||||||
|
|
||||||
<div myClick2 (myClick)="clickMessage2=$event">myClick2</div>
|
<div (myClick)="clickMessage2=$event">myClick2</div>
|
||||||
{{clickMessage2}}
|
{{clickMessage2}}
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- Pipes -->
|
<!-- Pipes -->
|
||||||
<hr><h2>Pipes</h2>
|
<hr><h2 id="pipes">Pipes</h2>
|
||||||
|
|
||||||
<!-- #docregion pipes-1 -->
|
<!-- #docregion pipes-1 -->
|
||||||
<!-- Force title to uppercase -->
|
<!-- Force title to uppercase -->
|
||||||
|
@ -596,9 +731,10 @@ bindon-ngModel
|
||||||
<label>Price: </label>{{product['price'] | currency:'$'}}
|
<label>Price: </label>{{product['price'] | currency:'$'}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- Null values and the Elvis operator -->
|
<!-- Null values and the Elvis operator -->
|
||||||
<hr><h2>Elvis</h2>
|
<hr><h2 id="elvis">Elvis <i>?.</i></h2>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<!-- #docregion elvis-1 -->
|
<!-- #docregion elvis-1 -->
|
||||||
|
@ -645,8 +781,16 @@ The null hero's name is {{nullHero.firstName}}
|
||||||
<!-- Todo: discuss this in the Style binding section -->
|
<!-- Todo: discuss this in the Style binding section -->
|
||||||
<!-- enums in bindings -->
|
<!-- enums in bindings -->
|
||||||
<!--
|
<!--
|
||||||
<hr><h2>Enums in binding</h2>
|
<hr><h2 id="enums">Enums in binding</h2>
|
||||||
|
|
||||||
<p>The current color number is {{color}}</p>
|
<p>The current color number is {{color}}</p>
|
||||||
<p><button [style.color]="color.toString()" (click)="colorToggle()">Enum Toggle</button>
|
<p><button [style.color]="color.toString()" (click)="colorToggle()">Enum Toggle</button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<!-- #docregion my-first-app -->
|
||||||
|
<h3>My First Angular Application</h3>
|
||||||
|
<!-- #enddocregion my-first-app -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
|
@ -8,4 +8,5 @@ img {height: 100px;}
|
||||||
.bad {color: red;}
|
.bad {color: red;}
|
||||||
.curly {font-family: "Brush Script MT"}
|
.curly {font-family: "Brush Script MT"}
|
||||||
.toe {margin-left: 1em; font-style: italic;}
|
.toe {margin-left: 1em; font-style: italic;}
|
||||||
little-hero {color:blue; font-size: smaller; background-color: Turquoise }
|
little-hero {color:blue; font-size: smaller; background-color: Turquoise }
|
||||||
|
.to-toc {margin-top: 10px; display: block}
|
|
@ -1,9 +1,44 @@
|
||||||
<!-- #docregion my-first-app -->
|
<!-- #docplaster -->
|
||||||
<h3>My First Angular Application</h3>
|
<a id="toc"></a>
|
||||||
<!-- #enddocregion my-first-app -->
|
<h1>Template Syntax</h1>
|
||||||
|
<a href="#interpolation">Interpolation</a><br>
|
||||||
|
<a href="#mental-model">Mental Model</a><br>
|
||||||
|
<a href="#buttons">Buttons</a><br>
|
||||||
|
<a href="#prop-vs-attrib">Properties vs. Attributes</a><br>
|
||||||
|
<br>
|
||||||
|
<a href="#property-binding">Property Binding</a><br>
|
||||||
|
<div style="margin-left:8px">
|
||||||
|
<a href="#attribute-binding">Attribute Binding</a><br>
|
||||||
|
<a href="#class-binding">Class Binding</a><br>
|
||||||
|
<a href="#style-binding">Style Binding</a><br>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<a href="#event-binding">Event Binding</a><br>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<div>Directives</div>
|
||||||
|
<div style="margin-left:8px">
|
||||||
|
<a href="#ngModel">NgModel (two-way) Binding</a><br>
|
||||||
|
<a href="#ngClass">NgClass Binding</a><br>
|
||||||
|
<a href="#ngStyle">NgStyle Binding</a><br>
|
||||||
|
<a href="#ngIf">NgIf</a><br>
|
||||||
|
<a href="#ngSwitch">NgSwitch</a><br>
|
||||||
|
<a href="#ngFor">NgFor</a><br>
|
||||||
|
<div style="margin-left:8px">
|
||||||
|
<a href="#ngFor-index">NgFor with index</a><br>
|
||||||
|
<a href="#ngFor-trackBy">NgFor with trackBy</a><br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<a href="#star-prefix">* prefix and <template></a><br>
|
||||||
|
<a href="#local-vars">Template local variables</a><br>
|
||||||
|
<a href="#inputs-and-outputs">Inputs and outputs</a><br>
|
||||||
|
<a href="#pipes">Pipes</a><br>
|
||||||
|
<a href="#elvis">Elvis <i>?.</i></a><br>
|
||||||
|
<a href="#enums">Enums</a><br>
|
||||||
|
|
||||||
<!-- Interpolation and expressions -->
|
<!-- Interpolation and expressions -->
|
||||||
<hr><h2>Interpolation</h2>
|
<hr><h2 id="interpolation">Interpolation</h2>
|
||||||
|
|
||||||
<!-- #docregion first-interpolation -->
|
<!-- #docregion first-interpolation -->
|
||||||
<p>My current hero is {{currentHero.firstName}}</p>
|
<p>My current hero is {{currentHero.firstName}}</p>
|
||||||
|
@ -26,9 +61,10 @@
|
||||||
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}</p>
|
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}</p>
|
||||||
<!-- #enddocregion sum-2 -->
|
<!-- #enddocregion sum-2 -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- New Mental Model -->
|
<!-- New Mental Model -->
|
||||||
<hr><h2>New Mental Model</h2>
|
<hr><h2 id="mental-model">New Mental Model</h2>
|
||||||
|
|
||||||
<!--<img src="http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png">-->
|
<!--<img src="http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png">-->
|
||||||
<!-- Public Domain terms of use: http://www.wpclipart.com/terms.html -->
|
<!-- Public Domain terms of use: http://www.wpclipart.com/terms.html -->
|
||||||
|
@ -65,11 +101,10 @@
|
||||||
</div>
|
</div>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<!-- See https://github.com/angular/angular/issues/5707 about "myClick (myClick)" -->
|
|
||||||
<!-- #docregion event-binding-syntax-1 -->
|
<!-- #docregion event-binding-syntax-1 -->
|
||||||
<button (click) = "onSave()">Save</button>
|
<button (click) = "onSave()">Save</button>
|
||||||
<hero-detail (deleted)="onHeroDeleted()"></hero-detail>
|
<hero-detail (deleted)="onHeroDeleted()"></hero-detail>
|
||||||
<div myClick (myClick)="clicked=$event">click me</div>
|
<div (myClick)="clicked=$event">click me</div>
|
||||||
<!-- #enddocregion event-binding-syntax-1 -->
|
<!-- #enddocregion event-binding-syntax-1 -->
|
||||||
{{clicked}}
|
{{clicked}}
|
||||||
<br><br>
|
<br><br>
|
||||||
|
@ -97,8 +132,10 @@
|
||||||
<!-- #enddocregion style-binding-syntax-1 -->
|
<!-- #enddocregion style-binding-syntax-1 -->
|
||||||
button</button>
|
button</button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- property vs. attribute -->
|
<!-- property vs. attribute -->
|
||||||
<hr><h2>Property vs. Attribute (img examples)</h2>
|
<hr><h2 id="prop-vs-attrib">Property vs. Attribute (img examples)</h2>
|
||||||
<!-- examine the following <img> tag in the browser tools -->
|
<!-- examine the following <img> tag in the browser tools -->
|
||||||
<img src="images/ng-logo.png"
|
<img src="images/ng-logo.png"
|
||||||
[src]="heroImageUrl">
|
[src]="heroImageUrl">
|
||||||
|
@ -109,10 +146,10 @@ button</button>
|
||||||
<img bind-src="heroImageUrl"/>
|
<img bind-src="heroImageUrl"/>
|
||||||
<img [attr.src]="villainImageUrl"/>
|
<img [attr.src]="villainImageUrl"/>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- buttons -->
|
<!-- buttons -->
|
||||||
<hr><h2>Buttons</h2>
|
<hr><h2 id="buttons">Buttons</h2>
|
||||||
|
|
||||||
<button>Enabled (but does nothing)</button>
|
<button>Enabled (but does nothing)</button>
|
||||||
<button disabled>Disabled</button>
|
<button disabled>Disabled</button>
|
||||||
|
@ -124,9 +161,10 @@ button</button>
|
||||||
<button bind-disabled="isUnchanged" on-click="onSave($event)">Disabled Cancel</button>
|
<button bind-disabled="isUnchanged" on-click="onSave($event)">Disabled Cancel</button>
|
||||||
<button [disabled]="!canSave" (click)="onSave($event)">Enabled Save</button>
|
<button [disabled]="!canSave" (click)="onSave($event)">Enabled Save</button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- property binding -->
|
<!-- property binding -->
|
||||||
<hr><h2>Property Binding</h2>
|
<hr><h2 id="property-binding">Property Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion property-binding-1 -->
|
<!-- #docregion property-binding-1 -->
|
||||||
<img [src]="heroImageUrl">
|
<img [src]="heroImageUrl">
|
||||||
|
@ -157,8 +195,10 @@ button</button>
|
||||||
<div [textContent]="'The title is '+title"></div>
|
<div [textContent]="'The title is '+title"></div>
|
||||||
<!-- #enddocregion property-binding-vs-interpolation -->
|
<!-- #enddocregion property-binding-vs-interpolation -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- attribute binding -->
|
<!-- attribute binding -->
|
||||||
<hr><h2>Attribute Binding</h2>
|
<hr><h2 id="attribute-binding">Attribute Binding</h2>
|
||||||
|
|
||||||
<!-- create and set a colspan attribute -->
|
<!-- create and set a colspan attribute -->
|
||||||
<!-- #docregion attrib-binding-colspan -->
|
<!-- #docregion attrib-binding-colspan -->
|
||||||
|
@ -195,12 +235,10 @@ button</button>
|
||||||
<button disabled [disabled]="false">Enabled (but inert)</button>
|
<button disabled [disabled]="false">Enabled (but inert)</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- class binding -->
|
<!-- class binding -->
|
||||||
<hr><h2>Class Binding</h2>
|
<hr><h2 id="class-binding">Class Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion class-binding-1 -->
|
<!-- #docregion class-binding-1 -->
|
||||||
<!-- standard class attribute setting -->
|
<!-- standard class attribute setting -->
|
||||||
|
@ -226,10 +264,10 @@ button</button>
|
||||||
|
|
||||||
<div bind-class.special="isSpecial">This class binding is special too</div>
|
<div bind-class.special="isSpecial">This class binding is special too</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!--style binding -->
|
<!--style binding -->
|
||||||
<hr><h2>Style Binding</h2>
|
<hr><h2 id="style-binding">Style Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion style-binding-1 -->
|
<!-- #docregion style-binding-1 -->
|
||||||
<button [style.color] = "isSpecial ? 'red' : 'green'">Red</button>
|
<button [style.color] = "isSpecial ? 'red' : 'green'">Red</button>
|
||||||
|
@ -241,8 +279,10 @@ button</button>
|
||||||
<button [style.fontSize.%]="!isSpecial ? 150 : 50" >Small</button>
|
<button [style.fontSize.%]="!isSpecial ? 150 : 50" >Small</button>
|
||||||
<!-- #enddocregion style-binding-2 -->
|
<!-- #enddocregion style-binding-2 -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- event binding -->
|
<!-- event binding -->
|
||||||
<hr><h2>Event Binding</h2>
|
<hr><h2 id="event-binding">Event Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion event-binding-1 -->
|
<!-- #docregion event-binding-1 -->
|
||||||
<button (click)="onSave()">Save</button>
|
<button (click)="onSave()">Save</button>
|
||||||
|
@ -257,7 +297,7 @@ button</button>
|
||||||
<!-- `myClick` is an event on the custom `MyClickDirective` -->
|
<!-- `myClick` is an event on the custom `MyClickDirective` -->
|
||||||
|
|
||||||
<!-- #docregion my-click -->
|
<!-- #docregion my-click -->
|
||||||
<div myClick (myClick)="clickMessage=$event">click with myClick</div>
|
<div (myClick)="clickMessage=$event">click with myClick</div>
|
||||||
<!-- #enddocregion my-click -->
|
<!-- #enddocregion my-click -->
|
||||||
<!-- #enddocregion event-binding-3 -->
|
<!-- #enddocregion event-binding-3 -->
|
||||||
{{clickMessage}}
|
{{clickMessage}}
|
||||||
|
@ -298,10 +338,11 @@ button</button>
|
||||||
<!-- #enddocregion event-binding-propagation -->
|
<!-- #enddocregion event-binding-propagation -->
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- Two way data binding unwound;
|
<!-- Two way data binding unwound;
|
||||||
passing the changed display value to the event handler via `$event` -->
|
passing the changed display value to the event handler via `$event` -->
|
||||||
<hr><h2>NgModel Binding</h2>
|
<hr><h2 id="ngModel">NgModel (two-way) Binding</h2>
|
||||||
|
|
||||||
<h3>Result: {{currentHero.firstName}}</h3>
|
<h3>Result: {{currentHero.firstName}}</h3>
|
||||||
|
|
||||||
|
@ -336,10 +377,10 @@ bindon-ngModel
|
||||||
(ngModelChange) = "setUpperCaseFirstName($event)"
|
(ngModelChange) = "setUpperCaseFirstName($event)"
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgClass binding -->
|
<!-- NgClass binding -->
|
||||||
<hr><h2>NgClass Binding</h2>
|
<hr><h2 id="ngClass">NgClass Binding</h2>
|
||||||
|
|
||||||
<p>setClasses returns {{setClasses() | json}}</p>
|
<p>setClasses returns {{setClasses() | json}}</p>
|
||||||
<!-- #docregion NgClass-1 -->
|
<!-- #docregion NgClass-1 -->
|
||||||
|
@ -356,9 +397,10 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
<div class="bad curly special">Bad curly special</div>
|
<div class="bad curly special">Bad curly special</div>
|
||||||
<div [ngClass]="{bad:false, curly:true, special:true}">Curly special</div>
|
<div [ngClass]="{bad:false, curly:true, special:true}">Curly special</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgStyle binding -->
|
<!-- NgStyle binding -->
|
||||||
<hr><h2>NgStyle Binding</h2>
|
<hr><h2 id="ngStyle">NgStyle Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion NgStyle-1 -->
|
<!-- #docregion NgStyle-1 -->
|
||||||
<div [style.fontSize]="isSpecial ? 'x-large' : 'smaller'" >
|
<div [style.fontSize]="isSpecial ? 'x-large' : 'smaller'" >
|
||||||
|
@ -381,10 +423,10 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
|
|
||||||
<!-- not used in chapter -->
|
<!-- not used in chapter -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgIf binding -->
|
<!-- NgIf binding -->
|
||||||
<hr><h2>NgIf Binding</h2>
|
<hr><h2 id="ngIf">NgIf Binding</h2>
|
||||||
|
|
||||||
<!-- #docregion NgIf-1 -->
|
<!-- #docregion NgIf-1 -->
|
||||||
<div *ngIf="currentHero">Hello, {{currentHero.firstName}}</div>
|
<div *ngIf="currentHero">Hello, {{currentHero.firstName}}</div>
|
||||||
|
@ -399,7 +441,6 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
<hero-detail *ngIf="isActive"></hero-detail>
|
<hero-detail *ngIf="isActive"></hero-detail>
|
||||||
<!-- #enddocregion NgIf-2 -->
|
<!-- #enddocregion NgIf-2 -->
|
||||||
|
|
||||||
|
|
||||||
<!-- NgIf binding with template (no *) -->
|
<!-- NgIf binding with template (no *) -->
|
||||||
|
|
||||||
<template [ngIf]="currentHero">Add {{currentHero.firstName}} with template</template>
|
<template [ngIf]="currentHero">Add {{currentHero.firstName}} with template</template>
|
||||||
|
@ -422,10 +463,10 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
||||||
<!-- #enddocregion NgIf-3 -->
|
<!-- #enddocregion NgIf-3 -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgSwitch binding -->
|
<!-- NgSwitch binding -->
|
||||||
<hr><h2>NgSwitch Binding</h2>
|
<hr><h2 id="ngSwitch">NgSwitch Binding</h2>
|
||||||
|
|
||||||
<fieldset #toePicker (click)="toeChooser(toePicker)" >
|
<fieldset #toePicker (click)="toeChooser(toePicker)" >
|
||||||
<input type="radio" name="toes" value="Eenie">Eenie
|
<input type="radio" name="toes" value="Eenie">Eenie
|
||||||
|
@ -437,22 +478,38 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
|
|
||||||
<div class="toe">
|
<div class="toe">
|
||||||
<div *ngIf="!toeChoice">Pick a toe</div>
|
<div *ngIf="!toeChoice">Pick a toe</div>
|
||||||
<div *ngIf="toeChoice">You picked
|
<div *ngIf="toeChoice">
|
||||||
<!-- #docregion NgSwitch -->
|
You picked ...
|
||||||
|
<!-- #docregion NgSwitch, NgSwitch-expanded -->
|
||||||
<span [ngSwitch]="toeChoice">
|
<span [ngSwitch]="toeChoice">
|
||||||
<template [ngSwitchWhen]="'Eenie'">Eenie</template>
|
<!-- #enddocregion NgSwitch -->
|
||||||
<template [ngSwitchWhen]="'Meanie'">Meanie</template>
|
|
||||||
<template [ngSwitchWhen]="'Miney'">Miney</template>
|
|
||||||
<template [ngSwitchWhen]="'Moe'">Moe</template>
|
|
||||||
<template ngSwitchDefault>Other</template>
|
|
||||||
</span>
|
|
||||||
<!-- #enddocregion NgSwitch -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<!-- with *NgSwitch -->
|
||||||
|
<!-- #docregion NgSwitch -->
|
||||||
|
<span *ngSwitchWhen="'Eenie'">Eenie</span>
|
||||||
|
<span *ngSwitchWhen="'Meanie'">Meanie</span>
|
||||||
|
<span *ngSwitchWhen="'Miney'">Miney</span>
|
||||||
|
<span *ngSwitchWhen="'Moe'">Moe</span>
|
||||||
|
<span *ngSwitchDefault>other</span>
|
||||||
|
<!-- #enddocregion NgSwitch -->
|
||||||
|
|
||||||
|
<!-- with <template> -->
|
||||||
|
<template [ngSwitchWhen]="'Eenie'"><span>Eenie</span></template>
|
||||||
|
<template [ngSwitchWhen]="'Meanie'"><span>Meanie</span></template>
|
||||||
|
<template [ngSwitchWhen]="'Miney'"><span>Miney</span></template>
|
||||||
|
<template [ngSwitchWhen]="'Moe'"><span>Moe</span></template>
|
||||||
|
<template ngSwitchDefault><span>other</span></template>
|
||||||
|
|
||||||
|
<!-- #docregion NgSwitch -->
|
||||||
|
</span>
|
||||||
|
<!-- #enddocregion NgSwitch, NgSwitch-expanded -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- NgFor binding -->
|
<!-- NgFor binding -->
|
||||||
<hr><h2>NgFor Binding</h2>
|
<hr><h2 id="ngFor">NgFor Binding</h2>
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- #docregion NgFor-1 -->
|
<!-- #docregion NgFor-1 -->
|
||||||
|
@ -467,52 +524,125 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
<hero-detail *ngFor="#hero of heroes" [hero]="hero"></hero-detail>
|
<hero-detail *ngFor="#hero of heroes" [hero]="hero"></hero-detail>
|
||||||
<!-- #enddocregion NgFor-2 -->
|
<!-- #enddocregion NgFor-2 -->
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
|
<h4 id="ngFor-index">NgFor with index</h4>
|
||||||
|
<p>with <i>semi-colon</i> separator</p>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- Ex: 1 - Hercules Son of Zeus -->
|
|
||||||
<!-- #docregion NgFor-3 -->
|
<!-- #docregion NgFor-3 -->
|
||||||
<div *ngFor="#hero of heroes, #i=index">{{i + 1}} - {{hero.fullName}}</div>
|
<div *ngFor="#hero of heroes; #i=index">{{i + 1}} - {{hero.fullName}}</div>
|
||||||
<!-- #enddocregion NgFor-3 -->
|
<!-- #enddocregion NgFor-3 -->
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
|
<p>with <i>comma</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- Ex: "1 - Hercules Son of Zeus"" -->
|
||||||
|
<div *ngFor="#hero of heroes, #i=index">{{i + 1}} - {{hero.fullName}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
|
<h4 id="ngFor-trackBy">NgForTrackBy</h4>
|
||||||
|
<button (click)="refreshHeroes()">Refresh heroes</button>
|
||||||
|
<p>First hero: <input [(ngModel)]="heroes[0].firstName"></p>
|
||||||
|
|
||||||
|
<p><i>without</i> trackBy</p>
|
||||||
|
<div #noTrackBy class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-1 -->
|
||||||
|
<div *ngFor="#hero of heroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-1 -->
|
||||||
|
</div>
|
||||||
|
<div id="noTrackByCnt" *ngIf="heroesNoTrackByChangeCount" style="background-color:bisque">
|
||||||
|
Hero DOM elements change #<span style="background-color:gold">{{heroesNoTrackByChangeCount}}</span> without trackBy
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>semi-colon</i> separator</p>
|
||||||
|
<div #withTrackBy class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-2 -->
|
||||||
|
<div *ngFor="#hero of heroes; trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-2 -->
|
||||||
|
</div>
|
||||||
|
<div id="withTrackByCnt" *ngIf="heroesWithTrackByChangeCount" style="background-color:bisque">
|
||||||
|
Hero DOM elements change #<span style="background-color:gold">{{heroesWithTrackByChangeCount}}</span> with trackBy
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>comma</i> separator</p>
|
||||||
|
<div class="box">
|
||||||
|
<div *ngFor="#hero of heroes, trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with trackBy and <i>space</i> separator</p>
|
||||||
|
<div #withTrackBy class="box">
|
||||||
|
<div *ngFor="#hero of heroes trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with <i>*ngForTrackBy</i></p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-2 -->
|
||||||
|
<div *ngFor="#hero of heroes" *ngForTrackBy="trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-2 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>with <i>generic</i> trackById function</p>
|
||||||
|
<div class="box">
|
||||||
|
<!-- #docregion NgForTrackBy-3 -->
|
||||||
|
<div *ngFor="#hero of heroes" *ngForTrackBy="trackById">({{hero.id}}) {{hero.fullName}}</div>
|
||||||
|
<!-- #enddocregion NgForTrackBy-3 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- * and template -->
|
<!-- * and template -->
|
||||||
<hr><h2>* and Template</h2>
|
<hr><h2 id="star-prefix">* prefix and <template></h2>
|
||||||
|
|
||||||
<h3>NgIf expansion</h3>
|
<h3>*ngIf expansion</h3>
|
||||||
|
<p><i>*ngIf</i></p>
|
||||||
<!-- #docregion Template-1 -->
|
<!-- #docregion Template-1 -->
|
||||||
<hero-detail *ngIf="currentHero" [hero]="currentHero"></hero-detail>
|
<hero-detail *ngIf="currentHero" [hero]="currentHero"></hero-detail>
|
||||||
<!-- #enddocregion Template-1 -->
|
<!-- #enddocregion Template-1 -->
|
||||||
|
|
||||||
|
<p><i>expand to template = "..."</i></p>
|
||||||
|
<!-- #docregion Template-2a -->
|
||||||
|
<hero-detail template="ngIf:currentHero" [hero]="currentHero"></hero-detail>
|
||||||
|
<!-- #enddocregion Template-2a -->
|
||||||
|
|
||||||
|
<p><i>expand to <template></i></p>
|
||||||
<!-- #docregion Template-2 -->
|
<!-- #docregion Template-2 -->
|
||||||
<template [ngIf]="currentHero">
|
<template [ngIf]="currentHero">
|
||||||
<hero-detail [hero]="currentHero"></hero-detail>
|
<hero-detail [hero]="currentHero"></hero-detail>
|
||||||
</template>
|
</template>
|
||||||
<!-- #enddocregion Template-2 -->
|
<!-- #enddocregion Template-2 -->
|
||||||
|
|
||||||
<h3>NgFor expansion</h3>
|
<h3>*ngFor expansion</h3>
|
||||||
|
<p><i>*ngFor</i></p>
|
||||||
|
<!-- *ngFor w/ hero-detail Component -->
|
||||||
|
<!-- #docregion Template-3a -->
|
||||||
|
<hero-detail *ngFor="#hero of heroes; trackBy:trackByHeroes" [hero]="hero"></hero-detail>
|
||||||
|
<!-- #enddocregion Template-3a -->
|
||||||
|
|
||||||
|
<p><i>expand to template = "..."</i></p>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- ngFor w/ hero-detail Component and a template "attribute" directive -->
|
<!-- ngFor w/ hero-detail Component and a template "attribute" directive -->
|
||||||
<!-- #docregion Template-3 -->
|
<!-- #docregion Template-3 -->
|
||||||
<hero-detail template="ngFor #hero of heroes" [hero]="hero"></hero-detail>
|
<hero-detail template="ngFor #hero of heroes; trackBy:trackByHeroes" [hero]="hero"></hero-detail>
|
||||||
<!-- #enddocregion Template-3 -->
|
<!-- #enddocregion Template-3 -->
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
|
|
||||||
|
<p><i>expand to <template></i></p>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<!-- ngFor w/ hero-detail Component inside a template element -->
|
<!-- ngFor w/ hero-detail Component inside a template element -->
|
||||||
<!-- #docregion Template-4 -->
|
<!-- #docregion Template-4 -->
|
||||||
<template ngFor #hero [ngForOf]="heroes">
|
<template ngFor #hero [ngForOf]="heroes" [ngForTrackBy]="trackByHeroes">
|
||||||
<hero-detail [hero]="hero"></hero-detail>
|
<hero-detail [hero]="hero"></hero-detail>
|
||||||
</template>
|
</template>
|
||||||
<!-- #enddocregion Template-4 -->
|
<!-- #enddocregion Template-4 -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- template local variable -->
|
<!-- template local variable -->
|
||||||
<hr><h2>Template local variables</h2>
|
<hr><h2 id="local-vars">Template local variables</h2>
|
||||||
|
|
||||||
<!-- #docregion var-phone -->
|
<!-- #docregion var-phone -->
|
||||||
<!-- phone refers to the input element; pass its `value` to an event handler -->
|
<!-- phone refers to the input element; pass its `value` to an event handler -->
|
||||||
|
@ -544,8 +674,10 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
<!-- btn refers to the button element; show its disabled state -->
|
<!-- btn refers to the button element; show its disabled state -->
|
||||||
<button #btn disabled [textContent]="'disabled by attribute: '+btn.disabled"></button>
|
<button #btn disabled [textContent]="'disabled by attribute: '+btn.disabled"></button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- inputs and output -->
|
<!-- inputs and output -->
|
||||||
<hr><h2>Inputs and Outputs</h2>
|
<hr><h2 id="inputs-and-outputs">Inputs and Outputs</h2>
|
||||||
|
|
||||||
<!-- #docregion io-1 -->
|
<!-- #docregion io-1 -->
|
||||||
<img [src]="iconUrl"/>
|
<img [src]="iconUrl"/>
|
||||||
|
@ -557,11 +689,13 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
</hero-detail>
|
</hero-detail>
|
||||||
<!-- #enddocregion io-2 -->
|
<!-- #enddocregion io-2 -->
|
||||||
|
|
||||||
<div myClick2 (myClick)="clickMessage2=$event">myClick2</div>
|
<div (myClick)="clickMessage2=$event">myClick2</div>
|
||||||
{{clickMessage2}}
|
{{clickMessage2}}
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- Pipes -->
|
<!-- Pipes -->
|
||||||
<hr><h2>Pipes</h2>
|
<hr><h2 id="pipes">Pipes</h2>
|
||||||
|
|
||||||
<!-- #docregion pipes-1 -->
|
<!-- #docregion pipes-1 -->
|
||||||
<!-- Force title to uppercase -->
|
<!-- Force title to uppercase -->
|
||||||
|
@ -597,9 +731,10 @@ After setClasses(), the classes are "{{classDiv.className}}"
|
||||||
<label>Price: </label>{{product.price | currency:'USD':true}}
|
<label>Price: </label>{{product.price | currency:'USD':true}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- Null values and the Elvis operator -->
|
<!-- Null values and the Elvis operator -->
|
||||||
<hr><h2>Elvis</h2>
|
<hr><h2 id="elvis">Elvis <i>?.</i></h2>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<!-- #docregion elvis-1 -->
|
<!-- #docregion elvis-1 -->
|
||||||
|
@ -646,10 +781,20 @@ The null hero's name is {{nullHero?.firstName}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
<!-- Todo: discuss this in the Style binding section -->
|
<!-- Todo: discuss this in the Style binding section -->
|
||||||
<!-- enums in bindings -->
|
<!-- enums in bindings -->
|
||||||
<hr><h2>Enums in binding</h2>
|
<hr><h2 id="enums">Enums in binding</h2>
|
||||||
|
|
||||||
<p>The name of the Color.Red enum is {{Color[Color.Red]}}</p>
|
<p>The name of the Color.Red enum is {{Color[Color.Red]}}</p>
|
||||||
<p>The current color number is {{color}}</p>
|
<p>The current color number is {{color}}</p>
|
||||||
<p><button [style.color]="Color[color]" (click)="colorToggle()">Enum Toggle</button>
|
<p><button [style.color]="Color[color]" (click)="colorToggle()">Enum Toggle</button>
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
||||||
|
<!-- #docregion my-first-app -->
|
||||||
|
<h3>My First Angular Application</h3>
|
||||||
|
<!-- #enddocregion my-first-app -->
|
||||||
|
|
||||||
|
<a class="to-toc" href="#toc">top</a>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//#docplaster
|
//#docplaster
|
||||||
|
|
||||||
import {Component} from 'angular2/core';
|
import {Component, AfterViewInit, ElementRef, OnInit, QueryList, ViewChildren} from 'angular2/core';
|
||||||
import {NgForm} from 'angular2/common';
|
import {NgForm} from 'angular2/common';
|
||||||
|
|
||||||
import {Hero} from './hero';
|
import {Hero} from './hero';
|
||||||
|
@ -25,7 +25,15 @@ export enum Color {Red, Green, Blue};
|
||||||
MyClickDirective, MyClickDirective2
|
MyClickDirective, MyClickDirective2
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent implements AfterViewInit, OnInit {
|
||||||
|
|
||||||
|
ngOnInit(){
|
||||||
|
this.refreshHeroes();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this._detectNgForTrackByEffects();
|
||||||
|
}
|
||||||
|
|
||||||
actionName = 'Go for it';
|
actionName = 'Go for it';
|
||||||
alert = alerter;
|
alert = alerter;
|
||||||
|
@ -56,7 +64,7 @@ export class AppComponent {
|
||||||
|
|
||||||
getVal() {return this.val};
|
getVal() {return this.val};
|
||||||
|
|
||||||
heroes = Hero.MockHeroes;
|
heroes:Hero[];
|
||||||
|
|
||||||
// heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png';
|
// heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png';
|
||||||
// Public Domain terms of use: http://www.wpclipart.com/terms.html
|
// Public Domain terms of use: http://www.wpclipart.com/terms.html
|
||||||
|
@ -101,6 +109,26 @@ export class AppComponent {
|
||||||
price: 42
|
price: 42
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// #docregion refresh-heroes
|
||||||
|
// update this.heroes with fresh set of cloned heroes
|
||||||
|
refreshHeroes() {
|
||||||
|
this.heroes = Hero.MockHeroes.map(hero => Hero.clone(hero));
|
||||||
|
}
|
||||||
|
// #enddocregion refresh-heroes
|
||||||
|
|
||||||
|
// #docregion same-as-it-ever-was
|
||||||
|
private _samenessCount = 5;
|
||||||
|
moreOfTheSame() {this._samenessCount++;};
|
||||||
|
get sameAsItEverWas() {
|
||||||
|
var result:string[] = Array(this._samenessCount);
|
||||||
|
for (var i=result.length; i-- > 0;){result[i]='same as it ever was ...'}
|
||||||
|
return result;
|
||||||
|
// return [1,2,3,4,5].map(id => {
|
||||||
|
// return {id:id, text: 'same as it ever was ...'};
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
// #enddocregion same-as-it-ever-was
|
||||||
|
|
||||||
setUpperCaseFirstName(firstName:string){
|
setUpperCaseFirstName(firstName:string){
|
||||||
//console.log(firstName);
|
//console.log(firstName);
|
||||||
this.currentHero.firstName = firstName.toUpperCase();
|
this.currentHero.firstName = firstName.toUpperCase();
|
||||||
|
@ -153,10 +181,62 @@ export class AppComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
title = 'Template Syntax'
|
title = 'Template Syntax';
|
||||||
|
|
||||||
|
// #docregion trackByHeroes
|
||||||
|
trackByHeroes(index: number, hero: Hero) { return hero.id; }
|
||||||
|
// #enddocregion trackByHeroes
|
||||||
|
|
||||||
|
// #docregion trackById
|
||||||
|
trackById(index: number, item: any): string { return item['id']; }
|
||||||
|
// #enddocregion trackById
|
||||||
|
|
||||||
val=2;
|
val=2;
|
||||||
// villainImageUrl = 'http://www.clker.com/cliparts/u/s/y/L/x/9/villain-man-hi.png'
|
// villainImageUrl = 'http://www.clker.com/cliparts/u/s/y/L/x/9/villain-man-hi.png'
|
||||||
// Public Domain terms of use http://www.clker.com/disclaimer.html
|
// Public Domain terms of use http://www.clker.com/disclaimer.html
|
||||||
villainImageUrl = 'images/villain.png'
|
villainImageUrl = 'images/villain.png'
|
||||||
|
|
||||||
|
|
||||||
|
//////// Detect effects of NgForTrackBy ///////////////
|
||||||
|
@ViewChildren('noTrackBy') childrenNoTrackBy:QueryList<ElementRef>;
|
||||||
|
@ViewChildren('withTrackBy') childrenWithTrackBy:QueryList<ElementRef>;
|
||||||
|
|
||||||
|
private _oldNoTrackBy:HTMLElement[];
|
||||||
|
private _oldWithTrackBy:HTMLElement[];
|
||||||
|
|
||||||
|
heroesNoTrackByChangeCount = 0;
|
||||||
|
heroesWithTrackByChangeCount = 0;
|
||||||
|
|
||||||
|
private _detectNgForTrackByEffects() {
|
||||||
|
this._oldNoTrackBy = toArray(this.childrenNoTrackBy);
|
||||||
|
this._oldWithTrackBy = toArray(this.childrenWithTrackBy);
|
||||||
|
|
||||||
|
this.childrenNoTrackBy.changes.subscribe((changes:any) => {
|
||||||
|
let newNoTrackBy = toArray(changes);
|
||||||
|
let isSame = this._oldNoTrackBy.every((v:any, i:number) => v === newNoTrackBy[i]);
|
||||||
|
if (!isSame) {
|
||||||
|
this._oldNoTrackBy = newNoTrackBy;
|
||||||
|
this.heroesNoTrackByChangeCount++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.childrenWithTrackBy.changes.subscribe((changes:any) => {
|
||||||
|
let newWithTrackBy = toArray(changes);
|
||||||
|
let isSame = this._oldWithTrackBy.every((v:any, i:number) => v === newWithTrackBy[i]);
|
||||||
|
if (!isSame) {
|
||||||
|
this._oldWithTrackBy = newWithTrackBy;
|
||||||
|
this.heroesWithTrackByChangeCount++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
///////////////////
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helper to convert viewChildren to an array of HTMLElements
|
||||||
|
function toArray(viewChildren:QueryList<ElementRef>) {
|
||||||
|
let result: HTMLElement[] = [];
|
||||||
|
let children = viewChildren.toArray()[0].nativeElement.children;
|
||||||
|
for (var i = 0; i < children.length; i++) { result.push(children[i]); }
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -6,10 +6,15 @@ export class Hero {
|
||||||
public lastName?:string,
|
public lastName?:string,
|
||||||
public birthdate?:Date,
|
public birthdate?:Date,
|
||||||
public url?:string,
|
public url?:string,
|
||||||
public rate:number = 100) {
|
public rate:number = 100,
|
||||||
this.id = Hero.nextId++;
|
id?:number) {
|
||||||
|
this.id = id != null ? id : Hero.nextId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static clone({firstName, lastName, birthdate, url, rate, id} : Hero){
|
||||||
|
return new Hero (firstName, lastName, birthdate, url, rate, id );
|
||||||
|
}
|
||||||
|
|
||||||
get fullName() {return `${this.firstName} ${this.lastName}`;}
|
get fullName() {return `${this.firstName} ${this.lastName}`;}
|
||||||
|
|
||||||
static nextId = 1;
|
static nextId = 1;
|
||||||
|
|
|
@ -8,4 +8,5 @@ img {height: 100px;}
|
||||||
.bad {color: red;}
|
.bad {color: red;}
|
||||||
.curly {font-family: "Brush Script MT"}
|
.curly {font-family: "Brush Script MT"}
|
||||||
.toe {margin-left: 1em; font-style: italic;}
|
.toe {margin-left: 1em; font-style: italic;}
|
||||||
little-hero {color:blue; font-size: smaller; background-color: Turquoise }
|
little-hero {color:blue; font-size: smaller; background-color: Turquoise }
|
||||||
|
.to-toc {margin-top: 10px; display: block}
|
|
@ -285,10 +285,17 @@ table
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-6')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-6')
|
||||||
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-3')(format=".")
|
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-3')(format=".")
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-7')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-7')
|
||||||
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngForTrackBy-1')
|
||||||
|
+makeExample('template-syntax/dart/lib/app_component.dart', 'trackByHeroes')(format=".")
|
||||||
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngForTrackBy-2')
|
||||||
|
+makeExample('template-syntax/dart/lib/app_component.html', 'NgForTrackBy-2')(format=".")
|
||||||
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngForTrackBy-3')
|
||||||
|
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template')
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-1')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-1')
|
||||||
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-1')(format=".")
|
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-1')(format=".")
|
||||||
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-2a')
|
||||||
|
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-2a')(format=".")
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-2')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-2')
|
||||||
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-2')(format=".")
|
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-2')(format=".")
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-3')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-3')
|
||||||
|
@ -299,8 +306,11 @@ table
|
||||||
Don’t make the mistake of writing `ngIf="currentHero"`!
|
Don’t make the mistake of writing `ngIf="currentHero"`!
|
||||||
That syntax assigns the *string* value "currentHero" to `ngIf`,
|
That syntax assigns the *string* value "currentHero" to `ngIf`,
|
||||||
which won't work because `ngIf` expects a bool. **[QUESTION: Did I get that right?]**
|
which won't work because `ngIf` expects a bool. **[QUESTION: Did I get that right?]**
|
||||||
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngSwitch-1')
|
||||||
|
+makeExample('template-syntax/dart/lib/app_component.html', 'NgSwitch-expanded')
|
||||||
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngSwitch-2')
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-1')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-1')
|
||||||
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-2')(format=".")
|
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-3a')(format=".")
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-2')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-2')
|
||||||
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-3')(format=".")
|
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-3')(format=".")
|
||||||
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-3')
|
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-3')
|
||||||
|
|
|
@ -18,6 +18,11 @@ include ../../../../_includes/_util-fns
|
||||||
* [Event binding](#event-binding)
|
* [Event binding](#event-binding)
|
||||||
* [Two-way data binding with `NgModel`](#ngModel)
|
* [Two-way data binding with `NgModel`](#ngModel)
|
||||||
* [Built-in directives](#directives)
|
* [Built-in directives](#directives)
|
||||||
|
* [NgClass](#ngClass)
|
||||||
|
* [NgStyle](#ngStyle)
|
||||||
|
* [NgIf](#ngIf)
|
||||||
|
* [NgSwitch](#ngSwitch)
|
||||||
|
* [NgFor](#ngFor)
|
||||||
* [* and <template>](#star-template)
|
* [* and <template>](#star-template)
|
||||||
* [Local template variables](#local-vars)
|
* [Local template variables](#local-vars)
|
||||||
* [Input and output properties](#inputs-outputs)
|
* [Input and output properties](#inputs-outputs)
|
||||||
|
@ -1078,18 +1083,35 @@ figure.image-display
|
||||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch')(format=".")
|
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch')(format=".")
|
||||||
// #docregion directives-ngSwitch-2
|
// #docregion directives-ngSwitch-2
|
||||||
:marked
|
:marked
|
||||||
We bind the parent `NgSwitch` directive to an expression returning a *switch value*. The value is a string in this example, but it can be a value of any type.
|
We bind the parent `NgSwitch` directive to an expression returning a *switch value*.
|
||||||
|
The value is a string in this example, but it can be a value of any type.
|
||||||
|
|
||||||
The parent `NgSwitch` directive controls a set of child`<template>` elements. Each `<template>` wraps a candidate subtree. A template is either pegged to a “match value” expression or marked as the default template.
|
In this example, the parent `NgSwitch` directive controls a set of child `<span>` elements.
|
||||||
|
A `<span>` is either pegged to a *match value* expression or marked as the default.
|
||||||
|
|
||||||
**At any particular moment, at most one of these templates is in the DOM.**
|
**At any particular moment, at most one of these *spans* is in the DOM.**
|
||||||
|
|
||||||
If the template’s *match value* equals the switch value, Angular adds the template’s subtree to the DOM. If no template is a match and there is a default template, Angular adds the default template’s subtree to the DOM. Angular removes and destroys the subtrees of all other templates.
|
|
||||||
|
|
||||||
|
If the *span*’s *match value* equals the switch value, Angular adds the `<span>` to the DOM.
|
||||||
|
If none of the *spans* is a match, Angular adds the default *span* to the DOM.
|
||||||
|
Angular removes and destroys all other *spans*.
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
We could substitute any element for the *span* in this example.
|
||||||
|
That element could be a `<div>` with a vast subtree of its own elements.
|
||||||
|
Only the matching `<div>` and its subtree would appear in the DOM;
|
||||||
|
the others would be removed.
|
||||||
|
:marked
|
||||||
Three collaborating directives are at work here:
|
Three collaborating directives are at work here:
|
||||||
1. `ngSwitch`: bound to an expression that returns the switch value
|
1. `ngSwitch`: bound to an expression that returns the switch value
|
||||||
1. `ngSwitchWhen`: bound to an expression returning a match value
|
1. `ngSwitchWhen`: bound to an expression returning a match value
|
||||||
1. `ngSwitchDefault`: a marker attribute on the default template
|
1. `ngSwitchDefault`: a marker attribute on the default element
|
||||||
|
|
||||||
|
.alert.is-critical
|
||||||
|
:marked
|
||||||
|
**Do *not*** put the asterisk (`*`) in front of `ngSwitch`. Use the property binding instead.
|
||||||
|
|
||||||
|
**Do** put the asterisk (`*`) in front of `ngSwitchWhen` and `ngSwitchDefault`.
|
||||||
|
For more information, see [\* and <template>](#star-template).
|
||||||
// #enddocregion directives-ngSwitch-2
|
// #enddocregion directives-ngSwitch-2
|
||||||
|
|
||||||
// #docregion directives-ngFor-1
|
// #docregion directives-ngFor-1
|
||||||
|
@ -1155,56 +1177,90 @@ figure.image-display
|
||||||
|
|
||||||
The next example captures the index in a variable named `i`, using it to stamp out rows like "1 - Hercules Son of Zeus".
|
The next example captures the index in a variable named `i`, using it to stamp out rows like "1 - Hercules Son of Zeus".
|
||||||
// #enddocregion directives-ngFor-6
|
// #enddocregion directives-ngFor-6
|
||||||
|
|
||||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgFor-3')(format=".")
|
+makeExample('template-syntax/ts/app/app.component.html', 'NgFor-3')(format=".")
|
||||||
// #docregion directives-ngFor-7
|
// #docregion directives-ngFor-7
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
Learn about other special values such as `last`, `even`, and `odd` in the [NgFor API reference](/docs/ts/latest/api/common/NgFor-directive.html).
|
Learn about other special *index-like* values such as `last`, `even`, and `odd` in the [NgFor API reference](/docs/ts/latest/api/common/NgFor-directive.html).
|
||||||
// #enddocregion directives-ngFor-7
|
// #enddocregion directives-ngFor-7
|
||||||
|
|
||||||
|
// #docregion directives-ngForTrackBy-1
|
||||||
|
:marked
|
||||||
|
#### NgForTrackBy
|
||||||
|
The `ngFor` directive has the potential to perform poorly, especially with large lists.
|
||||||
|
A small change to one item, an item removed, or an item added can trigger a cascade of DOM manipulations.
|
||||||
|
|
||||||
|
For example, we could refresh the list of heroes by re-querying the server.
|
||||||
|
The refreshed list probably contains most, if not all, of the previously displayed heroes.
|
||||||
|
|
||||||
|
*We* know this because the `id` of each hero hasn't changed.
|
||||||
|
But Angular sees only a fresh list of new object references.
|
||||||
|
It has no choice but to tear down the old list, discard those DOM elements, and re-build a new list with new DOM elements.
|
||||||
|
|
||||||
|
Angular can avoid this churn if we give it a *tracking* function that tells it what we know:
|
||||||
|
that two objects with the same `hero.id` are the same *hero*. Here is such a function:
|
||||||
|
// #enddocregion directives-ngForTrackBy-1
|
||||||
|
+makeExample('template-syntax/ts/app/app.component.ts', 'trackByHeroes')(format=".")
|
||||||
|
// #docregion directives-ngForTrackBy-2
|
||||||
|
:marked
|
||||||
|
Now set the `NgForTrackBy` directive to that *tracking* function.
|
||||||
|
Angular offers a variety of equivalent syntax choices including these two:
|
||||||
|
// #enddocregion directives-ngForTrackBy-2
|
||||||
|
+makeExample('template-syntax/ts/app/app.component.html', 'NgForTrackBy-2')(format=".")
|
||||||
|
// #docregion directives-ngForTrackBy-3
|
||||||
|
:marked
|
||||||
|
The *tracking* function doesn't eliminate all DOM changes.
|
||||||
|
Angular may have to update the DOM element if the same-hero *properties* have changed.
|
||||||
|
But if the properties haven't changed — and most of the time they will not have changed —
|
||||||
|
Angular can leave those DOM elements alone. The list UI will be smoother and more responsive.
|
||||||
|
|
||||||
|
Here is an illustration of the `NgForTrackBy` effect.
|
||||||
|
figure.image-display
|
||||||
|
img(src='/resources/images/devguide/template-syntax/ng-for-track-by-anim.gif' alt="NgForTrackBy")
|
||||||
|
// #enddocregion directives-ngForTrackBy-3
|
||||||
|
|
||||||
// #docregion star-template
|
// #docregion star-template
|
||||||
<a name="star-template"></a>
|
<a name="star-template"></a>
|
||||||
<a name="structural-directive"></a>
|
<a name="structural-directive"></a>
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## * and <template>
|
## * and <template>
|
||||||
When we reviewed the `NgFor` and `NgIf` built-in directives, we called out an oddity of the syntax: the asterisk (`*`) that appears before the directive name.
|
When we reviewed the `NgFor`, `NgIf`, and `NgSwitch` built-in directives, we called out an oddity of the syntax: the asterisk (`*`) that appears before the directive names.
|
||||||
|
|
||||||
The `*` is a bit of syntactic sugar that makes it easier to read and write directives that modify HTML layout
|
The `*` is a bit of syntactic sugar that makes it easier to read and write directives that modify HTML layout
|
||||||
with the help of templates.
|
with the help of templates.
|
||||||
`NgFor`, `NgIf`, and `NgSwitch` all add and remove element subtrees that are wrapped in `<template>` tags.
|
`NgFor`, `NgIf`, and `NgSwitch` all add and remove element subtrees that are wrapped in `<template>` tags.
|
||||||
|
|
||||||
With the [NgSwitch](#ngSwitch) directive we always write the `<template>` tags explicitly.
|
We didn't see the `<template>` tags because the `*` prefix syntax allowed us to skip those tags and
|
||||||
There isn’t much choice; we define a different template for each switch choice
|
focus directly on the HTML element that we are including, excluding, or repeating.
|
||||||
and let the directive render the template that matches the switch value.
|
|
||||||
|
In this section we go under the hood and see how
|
||||||
[NgFor](#ngFor) and [NgIf](#ngIf), on the other hand, each need only one template:
|
Angular strips away the `*` and expands the HTML into the `<template>` tags for us.
|
||||||
the *template-to-repeat* and the *template-to-include*, respectively.
|
|
||||||
|
|
||||||
The `*` prefix syntax is a convenient way to skip the `<template>` wrapper tags and
|
|
||||||
focus directly on the HTML element to repeat or include.
|
|
||||||
Angular sees the `*` and expands the HTML into the `<template>` tags for us.
|
|
||||||
// #enddocregion star-template
|
// #enddocregion star-template
|
||||||
|
|
||||||
// #docregion star-template-ngIf-1
|
// #docregion star-template-ngIf-1
|
||||||
:marked
|
:marked
|
||||||
### Expanding `*ngIf`
|
### Expanding `*ngIf`
|
||||||
We can do that expansion ourselves if we wish. Here's some code with `*ngIf`:
|
We can do what Angular does ourselves and expand the `*` prefix syntax to template syntax. Here's some code with `*ngIf`:
|
||||||
// #enddocregion star-template-ngIf-1
|
// #enddocregion star-template-ngIf-1
|
||||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-1')(format=".")
|
+makeExample('template-syntax/ts/app/app.component.html', 'Template-1')(format=".")
|
||||||
|
// #docregion star-template-ngIf-2a
|
||||||
|
:marked
|
||||||
|
The `currentHero` is referenced twice, first as the true/false condition for `NgIf` and
|
||||||
|
again as the actual hero passed into the `HeroDetailComponent`.
|
||||||
|
|
||||||
|
The first expansion step transports the `ngIf` (without the `*` prefix) and its contents
|
||||||
|
into an expression assigned to a `template` directive.
|
||||||
|
// #enddocregion star-template-ngIf-2a
|
||||||
|
+makeExample('template-syntax/ts/app/app.component.html', 'Template-2a')(format=".")
|
||||||
// #docregion star-template-ngIf-2
|
// #docregion star-template-ngIf-2
|
||||||
:marked
|
:marked
|
||||||
Here's the equivalent with `<template>` and `ngIf`:
|
The next (and final) step unfolds the HTML into a `<template>` tag and `[ngIf]` [property binding](#property-binding):
|
||||||
// #enddocregion star-template-ngIf-2
|
// #enddocregion star-template-ngIf-2
|
||||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-2')(format=".")
|
+makeExample('template-syntax/ts/app/app.component.html', 'Template-2')(format=".")
|
||||||
// #docregion star-template-ngIf-3
|
// #docregion star-template-ngIf-3
|
||||||
:marked
|
:marked
|
||||||
Notice that the `*` is gone and we have a [property binding](#property-binding) to the `ngIf`
|
Notice that the `[hero]="currentHero"` binding remains on the child `<hero-detail>`
|
||||||
directive, applied in this case to the `<template>` rather than
|
|
||||||
the application’s `hero-detail` component.
|
|
||||||
|
|
||||||
The `[hero]="currentHero"` binding remains on the child `<hero-detail>`
|
|
||||||
element inside the template.
|
element inside the template.
|
||||||
// #enddocregion star-template-ngIf-3
|
// #enddocregion star-template-ngIf-3
|
||||||
|
|
||||||
|
@ -1219,26 +1275,48 @@ figure.image-display
|
||||||
… even when there is no `currentHero`!
|
… even when there is no `currentHero`!
|
||||||
// #enddocregion star-template-ngIf-4
|
// #enddocregion star-template-ngIf-4
|
||||||
|
|
||||||
|
// #docregion star-template-ngSwitch-1
|
||||||
|
:marked
|
||||||
|
### Expanding `*ngSwitch`
|
||||||
|
A similar transformation applies to `*ngSwitch`. We can de-sugar the syntax ourselves.
|
||||||
|
Here's an example, first with `*ngSwitchWhen` and `*ngSwitchDefault` and then again with `<template>` tags:
|
||||||
|
// #enddocregion star-template-ngSwitch-1
|
||||||
|
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch-expanded')
|
||||||
|
// #docregion star-template-ngSwitch-2
|
||||||
|
:marked
|
||||||
|
The `*ngSwitchWhen` and `*ngSwitchDefault` expand in exactly the same manner as `*ngIf`,
|
||||||
|
wrapping their former elements in `<template>` tags.
|
||||||
|
|
||||||
|
Now we can see why the `ngSwitch` itself is not prefixed with an asterisk (*).
|
||||||
|
It does not define content. It's job is to control a collection of templates.
|
||||||
|
|
||||||
|
In this case, it governs two sets of `NgSwitchWhen` and `NgSwitchDefault` directives.
|
||||||
|
We should expect it to display the values of the selected template twice,
|
||||||
|
once for the (*) prefixed version and once for the expanded template version.
|
||||||
|
That's exactly what we see in this example:
|
||||||
|
figure.image-display
|
||||||
|
img(src='/resources/images/devguide/template-syntax/ng-switch-anim.gif' alt="NgSwitch")
|
||||||
|
// #enddocregion star-template-ngSwitch-2
|
||||||
// #docregion star-template-ngFor-1
|
// #docregion star-template-ngFor-1
|
||||||
:marked
|
:marked
|
||||||
### Expanding `*ngFor`
|
### Expanding `*ngFor`
|
||||||
A similar transformation applies to `*ngFor`. We can de-sugar the syntax ourselves. First, here's an example with `*ngFor`:
|
The `*ngFor` undergoes a similar transformation. We begin with an `*ngFor` example:
|
||||||
// #enddocregion star-template-ngFor-1
|
// #enddocregion star-template-ngFor-1
|
||||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgFor-2')(format=".")
|
+makeExample('template-syntax/ts/app/app.component.html', 'Template-3a')(format=".")
|
||||||
// #docregion star-template-ngFor-2
|
// #docregion star-template-ngFor-2
|
||||||
:marked
|
:marked
|
||||||
Here's the same example, slightly expanded:
|
Here's the same example after transporting the `ngFor` to the `template` directive:
|
||||||
// #enddocregion star-template-ngFor-2
|
// #enddocregion star-template-ngFor-2
|
||||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-3')(format=".")
|
+makeExample('template-syntax/ts/app/app.component.html', 'Template-3')(format=".")
|
||||||
// #docregion star-template-ngFor-3
|
// #docregion star-template-ngFor-3
|
||||||
:marked
|
:marked
|
||||||
And here it is, expanded further:
|
And here it is expanded further into a `<template>` tag wrapping the original `<hero-detail>` element:
|
||||||
// #enddocregion star-template-ngFor-3
|
// #enddocregion star-template-ngFor-3
|
||||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-4')(format=".")
|
+makeExample('template-syntax/ts/app/app.component.html', 'Template-4')(format=".")
|
||||||
// #docregion star-template-ngFor-4
|
// #docregion star-template-ngFor-4
|
||||||
:marked
|
:marked
|
||||||
The `NgFor` code is a bit more complex than `NgIf` because a repeater has more moving parts to configure.
|
The `NgFor` code is a bit more complex than `NgIf` because a repeater has more moving parts to configure.
|
||||||
In this case, we have to remember the `NgForOf` directive that identifies the list.
|
In this case, we have to remember to create and assign the `NgForOf` directive that identifies the list and the `NgForTrackBy` directive.
|
||||||
Using the `*ngFor` syntax is much easier than writing out this expanded HTML ourselves.
|
Using the `*ngFor` syntax is much easier than writing out this expanded HTML ourselves.
|
||||||
// #enddocregion star-template-ngFor-4
|
// #enddocregion star-template-ngFor-4
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 196 KiB |
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Loading…
Reference in New Issue