docs(template-syntax): drive jade from sample

closes #456
This commit is contained in:
Ward Bell 2015-12-07 13:31:26 -08:00
parent b7897eef85
commit c33ee37144
15 changed files with 1418 additions and 1264 deletions

View File

@ -11,11 +11,11 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"angular2": "2.0.0-alpha.46", "angular2": "2.0.0-alpha.48",
"systemjs": "0.19.2" "systemjs": "0.19.6"
}, },
"devDependencies": { "devDependencies": {
"live-server": "^0.8.1", "live-server": "^0.8.1",
"typescript": "^1.6.2" "typescript": "^1.7.2"
} }
} }

View File

@ -0,0 +1,658 @@
<!-- #docregion my-first-app -->
<h3>My First Angular Application</h3>
<!-- #enddocregion my-first-app -->
<!-- Interpolation and expressions -->
<hr><h2>Interpolation</h2>
<!-- #docregion first-interpolation -->
<p>My current hero is {{currentHero.firstName}}</p>
<!-- #enddocregion first-interpolation -->
<!-- #docregion title+image -->
<h3>
{{title}}
<img src="{{heroImageUrl}}" style="height:30px">
</h3>
<!-- #enddocregion title+image -->
<!-- #docregion sum-1 -->
<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{1 + 1}}</p>
<!-- #enddocregion sum-1 -->
<!-- #docregion sum-2 -->
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{1+1+getVal()}}</p>
<!-- #enddocregion sum-2 -->
<!-- New Mental Model -->
<hr><h2>New Mental Model</h2>
<!--<img src="http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png">-->
<!-- Public Domain terms of use: http://www.wpclipart.com/terms.html -->
<!-- #docregion img+button -->
<div class="special">Mental Model</div>
<div><b>{{currentHero.fullName}}</b></div>
<img src="images/hero.png">
<button disabled>Save</button>
<!-- #enddocregion img+button -->
<br><br>
<div>
<!-- #docregion hero-detail-1 -->
<div class="special">Mental Model</div>
<hero-detail></hero-detail>
<!-- #enddocregion hero-detail-1 -->
</div>
<br><br>
<div>
<!-- #docregion disabled-button-1 -->
<!-- Bind button disabled state to `isUnchanged` property -->
<button [disabled]="isUnchanged">Save</button>
<!-- #enddocregion disabled-button-1 -->
</div>
<br><br>
<div>
<!-- #docregion property-binding-syntax-1 -->
<img [src] = "heroImageUrl">
<hero-detail [hero]="currentHero"></hero-detail>
<div [ng-class] = "{selected: isSelected}"></div>
<!-- #enddocregion property-binding-syntax-1 -->
</div>
<br><br>
<!-- #docregion event-binding-syntax-1 -->
<button (click) = "onSave()">Save</button>
<hero-detail (deleted)="onHeroDeleted()"></hero-detail>
<div my-click (my-click)="clicked=$event">click me</div>
<!-- #enddocregion event-binding-syntax-1 -->
{{clicked}}
<br><br>
<div>
<!-- #docregion 2-way-binding-syntax-1 -->
<input [(ng-model)]="heroName">
<!-- #enddocregion 2-way-binding-syntax-1 -->
Hero Name: {{heroName}}
</div>
<br><br>
<!-- #docregion attribute-binding-syntax-1 -->
<button [attr.aria-label]="help">help</button>
<!-- #enddocregion attribute-binding-syntax-1 -->
<br><br>
<!-- #docregion class-binding-syntax-1 -->
<div [class.special]="isSpecial">Special</div>
<!-- #enddocregion class-binding-syntax-1 -->
<br><br>
<!-- #docregion style-binding-syntax-1 -->
<button [style.color] = "isSpecial ? 'red' : 'green'">
<!-- #enddocregion style-binding-syntax-1 -->
button</button>
<hr><h2>kebab-case</h2>
<!-- #docregion bad-mixed-case -->
<!-- BAD: mixed case target names don't work
<label [textContent] = "title"></label>
<hero-detail [isActive] = "isActive"></hero-detail>
-->
<!-- #enddocregion bad-mixed-case -->
<!-- #docregion kebab-case -->
<!-- lower kebab-case -->
<label [text-content] = "title"></label>
<hero-detail [is-active] = "isActive"></hero-detail>
<!-- #enddocregion kebab-case -->
<!-- property vs. attribute -->
<hr><h2>Property vs. Attribute (img examples)</h2>
<!-- examine the following <img> tag in the browser tools -->
<img src="images/ng-logo.png"
[src]="heroImageUrl">
<br><br>
<img [src]="iconUrl"/>
<img bind-src="heroImageUrl"/>
<img [attr.src]="villainImageUrl"/>
<!-- buttons -->
<hr><h2>Buttons</h2>
<button>Enabled (but does nothing)</button>
<button disabled>Disabled</button>
<button disabled=false>Still disabled</button>
<br><br>
<button disabled>disabled by attribute</button>
<button [disabled]="isUnchanged">disabled by property binding</button>
<br><br>
<button bind-disabled="isUnchanged" on-click="onSave($event)">Disabled Cancel</button>
<button [disabled]="!canSave" (click)="onSave($event)">Enabled Save</button>
<!-- property binding -->
<hr><h2>Property Binding</h2>
<!-- #docregion property-binding-1 -->
<img [src]="heroImageUrl">
<!-- #enddocregion property-binding-1 -->
<!-- #docregion property-binding-2 -->
<button [disabled]="isUnchanged">Cancel</button>
<!-- #enddocregion property-binding-2 -->
<!-- #docregion property-binding-3 -->
<div [ng-class]="'special'">NgClass is special</div>
<!-- #enddocregion property-binding-3 -->
<!-- #docregion property-binding-4 -->
<hero-detail [hero]="selectedHero"></hero-detail>
<!-- #enddocregion property-binding-4 -->
<!-- #docregion property-binding-5 -->
<img bind-src="heroImageUrl">
<!-- #enddocregion property-binding-5 -->
<!-- #docregion property-binding-6 -->
<!-- Doesn't work! HeroDetailComponent expects a Hero, not a string -->
<hero-detail hero="…what do we do here??? …"></hero-detail>
<!-- #enddocregion property-binding-6 -->
<!-- #docregion property-binding-v-interpolation -->
<img src="{{heroImageUrl}}">
<img [src]="'' + heroImageUrl">
<div>The title is {{title}}</div>
<div [text-content]="'The title is '+title"></div>
<!-- #enddocregion property-binding-v-interpolation -->
<!-- attribute binding -->
<hr><h2>Attribute Binding</h2>
<!-- create and set a colspan attribute -->
<!-- #docregion attrib-binding-colspan -->
<table border=1>
<!-- expression calculates colspan=2 -->
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
<!-- ERROR: There is no `colspan` property to set!
<tr><td colspan="{{1+1}}">Three-Four</td></tr>
-->
<tr><td>Five</td><td>Six</td></tr>
</table>
<!-- #enddocregion attrib-binding-colspan -->
<br>
<!-- #docregion attrib-binding-aria -->
<!-- create and set an aria attribute for assistive technology -->
<button [attr.aria-label]="actionName">{{actionName}} with Aria</button>
<!-- #enddocregion attrib-binding-aria -->
<br><br>
<!-- The following effects are not discussed in the chapter -->
<div>
<!-- any use of [attr.disabled] creates the disabled attribute -->
<button [attr.disabled]="isUnchanged">Disabled</button>
<button [attr.disabled]="!isUnchanged">Disabled as well</button>
<!-- can't remove it with [attr.disabled] either -->
<button disabled [attr.disabled]>Still disabled</button>
<!-- we'd have to remove it with property binding -->
<button disabled [disabled]="false">Enabled (but inert)</button>
</div>
<!-- class binding -->
<hr><h2>Class Binding</h2>
<!-- #docregion class-binding-1 -->
<!-- standard class attribute setting -->
<div class="bad curly special">Bad curly special</div>
<!-- #enddocregion class-binding-1 -->
<!-- #docregion class-binding-2 -->
<!-- reset all class names with a string binding -->
<div class="bad curly special"
[class]="'bad curly'">Bad curly</div>
<!-- #enddocregion class-binding-2 -->
<!-- #docregion class-binding-3 -->
<!-- #docregion class-binding-3a -->
<!-- toggle the "special" class on/off with a property -->
<div [class.special]="isSpecial">The class binding is special</div>
<!-- #enddocregion class-binding-3a -->
<!-- binding to `class.special` trumps the class attribute -->
<div class="special"
[class.special]="!isSpecial">This one is not so special</div>
<!-- #enddocregion class-binding-3 -->
<div bind-class.special="isSpecial">This class binding is special too</div>
<!--style binding -->
<hr><h2>Style Binding</h2>
<!-- #docregion style-binding-1 -->
<button [style.color] = "isSpecial ? 'red' : 'green'">Red</button>
<button [style.background-color]="canSave ?'cyan' : 'grey'" >Save</button>
<!-- #enddocregion style-binding-1 -->
<!-- #docregion style-binding-2 -->
<button [style.font-size.em]="isSpecial ? 3 : 1" >Big</button>
<button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>
<!-- #enddocregion style-binding-2 -->
<!-- event binding -->
<hr><h2>Event Binding</h2>
<!-- #docregion event-binding-1 -->
<button (click)="onSave()">Save</button>
<!-- #enddocregion event-binding-1 -->
<!-- #docregion event-binding-2 -->
<button on-click="onSave()">On Save</button>
<!-- #enddocregion event-binding-2 -->
<div>
<!-- #docregion event-binding-3 -->
<!-- `my-click` is an event on the custom `MyClickDirective` -->
<div my-click (my-click)="clickity=$event">click with my-click</div>
<!-- #enddocregion event-binding-3 -->
{{clickity}}
</div>
<!-- binding to a nested component -->
<!-- #docregion event-binding-to-component -->
<hero-detail (deleted)="onHeroDeleted($event)" [hero]="currentHero">
</hero-detail>
<!-- #enddocregion event-binding-to-component -->
<br>
<big-hero-detail
(deleted)="onHeroDeleted($event)"
[hero]="currentHero">
</big-hero-detail>
<!-- #docregion event-binding-bubbling -->
<div class="parent-div" (click)="onClickMe($event)">Click me
<div class="child-div">Click me too!</div>
</div>
<!-- #enddocregion event-binding-bubbling -->
<br><br>
<!-- #docregion event-binding-no-propagation -->
<!-- Will save only once -->
<div (click)="onSave()">
<button (click)="onSave()">Save, no propagation</button>
</div>
<!-- #enddocregion event-binding-no-propagation -->
<br><br>
<!-- #docregion event-binding-propagation -->
<!-- Will save twice -->
<div (click)="onSave()">
<button (click)="onSave() || true">Save w/ propagation</button>
</div>
<!-- #enddocregion event-binding-propagation -->
<br><br>
<!-- Two way data binding unwound;
passing the changed display value to the event handler via `$event` -->
<hr><h2>NgModel Binding</h2>
<h3>Result: {{currentHero.firstName}}</h3>
<!-- #docregion without-NgModel -->
<input [value]="currentHero.firstName"
(input)="currentHero.firstName=$event.target.value" >
<!-- #enddocregion without-NgModel -->
without NgModel
<br>
<!-- #docregion NgModel-1 -->
<input [(ng-model)]="currentHero.firstName">
<!-- #enddocregion NgModel-1 -->
[(ng-model)]
<br>
<!-- #docregion NgModel-2 -->
<input bindon-ng-model="currentHero.firstName">
<!-- #enddocregion NgModel-2 -->
bindon-ng-model
<br>
<!-- #docregion NgModel-3 -->
<input
[ng-model]="currentHero.firstName"
(ng-model-change)="currentHero.firstName=$event">
<!-- #enddocregion NgModel-3 -->
(ng-model-change) = "...firstName=$event"
<br>
<!-- #docregion NgModel-4 -->
<input
[ng-model]="currentHero.firstName"
(ng-model-change)="setUpperCaseFirstName($event)">
<!-- #enddocregion NgModel-4 -->
(ng-model-change) = "setUpperCaseFirstName($event)"
<br>
<!-- NgClass binding -->
<hr><h2>NgClass Binding</h2>
<p>setClasses returns {{setClasses() | json}}</p>
<!-- #docregion NgClass-1 -->
<div [ng-class]="setClasses()">This div is saveable and special</div>
<!-- #enddocregion NgClass-1 -->
<div [ng-class]="setClasses()" #class-div>
After setClasses(), the classes are "{{classDiv.className}}"
</div>
<!-- not used in chapter -->
<div [ng-class]="isSpecial ? 'special' : ''">This div is special</div>
<div class="bad curly special">Bad curly special</div>
<div [ng-class]="{bad:false, curly:true, special:true}">Curly special</div>
<!-- NgStyle binding -->
<hr><h2>NgStyle Binding</h2>
<!-- #docregion NgStyle-1 -->
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'" >
This div is x-large
</div>
<!-- #enddocregion NgStyle-1 -->
<p>setStyles returns {{setStyles() | json}}</p>
<!-- #docregion NgStyle-2 -->
<div [ng-style]="setStyles()">
This div is italic, normal weight, and x-large
</div>
<!-- #enddocregion NgStyle-2 -->
<div [ng-style]="setStyles()" #style-div>
After setStyles(), the styles are "{{getStyles(styleDiv)}}"
</div>
<!-- not used in chapter -->
<!-- NgIf binding -->
<hr><h2>NgIf Binding</h2>
<!-- #docregion NgIf-1 -->
<div *ng-if="currentHero">Hello, {{currentHero.firstName}}</div>
<!-- #enddocregion NgIf-1 -->
<!-- #docregion NgIf-2 -->
<!-- not displayed because nullHero is falsey.
`nullHero.firstName` never has a chance to fail -->
<div *ng-if="nullHero">Hello, {{nullHero.firstName}}</div>
<!-- Hero Detail is not in the DOM because isActive is false-->
<hero-detail *ng-if="isActive"></hero-detail>
<!-- #enddocregion NgIf-2 -->
<!-- NgIf binding with template (no *) -->
<template [ng-if]="currentHero">Add {{currentHero.firstName}} with template</template>
<!-- Does not show because isActive is false! -->
<div>Hero Detail removed from DOM (via template) because isActive is false</div>
<template [ng-if]="isActive">
<hero-detail></hero-detail>
</template>
<!-- #docregion NgIf-3 -->
<!-- isSpecial is true -->
<div [class.hidden]="!isSpecial">Show with class</div>
<div [class.hidden]="isSpecial">Hide with class</div>
<!-- HeroDetail is in the DOM but hidden -->
<hero-detail [class.hidden]="isSpecial"></hero-detail>
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
<!-- #enddocregion NgIf-3 -->
<!-- NgSwitch binding -->
<hr><h2>NgSwitch Binding</h2>
<fieldset #toe-picker (click)="null" >
<input type="radio" name="toes" value="Eenie">Eenie
<input type="radio" name="toes" checked value="Meanie">Meanie
<input type="radio" name="toes" value="Miney">Miney
<input type="radio" name="toes" value="Moe">Moe
<input type="radio" name="toes" value="???">???
</fieldset>
<!-- #docregion NgSwitch -->
<div class="toe">You picked
<span [ng-switch]="toeChoice(toePicker)">
<template [ng-switch-when]="'Eenie'">Eenie</template>
<template [ng-switch-when]="'Meanie'">Meanie</template>
<template [ng-switch-when]="'Miney'">Miney</template>
<template [ng-switch-when]="'Moe'">Moe</template>
<template ng-switch-default>Other</template>
</span>
</div>
<!-- #enddocregion NgSwitch -->
<!-- NgFor binding -->
<hr><h2>NgFor Binding</h2>
<div class="box">
<!-- #docregion NgFor-1 -->
<div *ng-for="#hero of heroes">{{hero.fullName}}</div>
<!-- #enddocregion NgFor-1 -->
</div>
<br>
<div class="box">
<!-- *ng-for w/ hero-detail Component -->
<!-- #docregion NgFor-2 -->
<hero-detail *ng-for="#hero of heroes" [hero]="hero"></hero-detail>
<!-- #enddocregion NgFor-2 -->
</div>
<br>
<div class="box">
<!-- Ex: 1 - Hercules Son of Zeus -->
<!-- #docregion NgFor-3 -->
<div *ng-for="#hero of heroes, #i=index">{{i+1}} - {{hero.fullName}}</div>
<!-- #enddocregion NgFor-3 -->
</div>
<br>
<!-- * and template -->
<hr><h2>* and Template</h2>
<h3>NgIf expansion</h3>
<!-- #docregion Template-1 -->
<hero-detail *ng-if="currentHero" [hero]="currentHero"></hero-detail>
<!-- #enddocregion Template-1 -->
<!-- #docregion Template-2 -->
<template [ng-if]="currentHero">
<hero-detail [hero]="currentHero"></hero-detail>
</template>
<!-- #enddocregion Template-2 -->
<h3>NgFor expansion</h3>
<div class="box">
<!-- ng-for w/ hero-detail Component and a template "attribute" directive -->
<!-- #docregion Template-3 -->
<hero-detail template="ng-for #hero of heroes" [hero]="hero"></hero-detail>
<!-- #enddocregion Template-3 -->
</div>
<br>
<div class="box">
<!-- ng-for w/ hero-detail Component inside a template element -->
<!-- #docregion Template-4 -->
<template ng-for #hero [ng-for-of]="heroes">
<hero-detail [hero]="hero"></hero-detail>
</template>
<!-- #enddocregion Template-4 -->
</div>
<!-- template local variable -->
<hr><h2>Template local variables</h2>
<!-- #docregion var-phone -->
<!-- phone refers to the input element; pass its `value` to an event handler -->
<input #phone placeholder="phone number">
<button (click)="callPhone(phone.value)">Call</button>
<!-- fax refers to the input element; pass its `value` to an event handler -->
<input var-fax placeholder="phone number">
<button (click)="callFax(fax.value)">Fax</button>
<!-- #enddocregion var-phone -->
<h4>Example Form</h4>
<!-- #docregion var-form -->
<!-- #docregion var-form-a -->
<form (ng-submit)="onSubmit(theForm)" #theForm="form">
<!-- #enddocregion var-form-a -->
<div class="form-group">
<label for="name">Name</label>
<input class="form-control" required ng-control="firstName"
[(ng-model)]="currentHero.firstName">
</div>
<!-- #docregion var-form-a -->
<button type="submit" [disabled]="!theForm.form.valid">Submit</button>
</form>
<!-- #enddocregion var-form-a -->
<!-- #enddocregion var-form -->
<br><br>
<!-- btn refers to the button element; show its disabled state -->
<button #btn disabled [text-content]="'disabled by attribute: '+btn.disabled"></button>
<!-- inputs and output -->
<hr><h2>Inputs and Outputs</h2>
<!-- #docregion io-1 -->
<img [src]="iconUrl"/>
<button (click)="onSave()">Save</button>
<!-- #enddocregion io-1 -->
<!-- #docregion io-2 -->
<hero-detail [hero]="currentHero" (deleted)="onHeroDeleted($event)">
</hero-detail>
<!-- #enddocregion io-2 -->
<div my-click2 (my-click)="clicked2=$event">my-click2</div>
{{clicked2}}
<!-- Pipes -->
<hr><h2>Pipes</h2>
<!-- #docregion pipes-1 -->
<!-- Force title to uppercase -->
<div>{{ title | uppercase }}</div>
<!-- #enddocregion pipes-1 -->
<!-- #docregion pipes-2 -->
<!-- Pipe chaining: force title to uppercase, then to lowercase -->
<div>{{ title | uppercase | lowercase }}</div>
<!-- #enddocregion pipes-2 -->
<!-- #docregion pipes-3 -->
<!-- pipe with configuration argument => "February 25, 1970" -->
<div>Birthdate: {{currentHero?.birthdate | date:'longDate'}}</div>
<!-- #enddocregion pipes-3 -->
<!-- #docregion pipes-json -->
<div>{{currentHero | json}}</div>
<!-- Output:
{ "firstName": "Hercules", "lastName": "Son of Zeus",
"birthdate": "1970-02-25T08:00:00.000Z",
"url": "http://www.imdb.com/title/tt0065832/",
"rate": 325, "id": 1 }
-->
<!-- #enddocregion pipes-json -->
<div>Birthdate: {{(currentHero?.birthdate | date:'longDate') | uppercase}}</div>
<div>
<!-- pipe price to USD and display the $ symbol -->
<label>Price: </label>{{product.price | currency:'USD':true}}
</div>
<!-- Null values and the Elvis operator -->
<hr><h2>Elvis</h2>
<div>
<!-- #docregion elvis-1 -->
The title is {{ title }}
<!-- #enddocregion elvis-1 -->
</div>
<div>
<!-- #docregion elvis-2 -->
The current hero's name is {{currentHero?.firstName}}
<!-- #enddocregion elvis-2 -->
</div>
<div>
<!-- #docregion elvis-3 -->
The current hero's name is {{currentHero.firstName}}
<!-- #enddocregion elvis-3 -->
</div>
<!--
The null hero's name is {{nullHero.firstName}}
See console log
TypeError: Cannot read property 'firstName' of null in [null]
-->
<!-- #docregion elvis-4 -->
<!--No hero, div not displayed, no error -->
<div *ng-if="nullHero">The null hero's name is {{nullHero.firstName}}</div>
<!-- #enddocregion elvis-4 -->
<div>
<!-- #docregion elvis-5 -->
The null hero's name is {{nullHero && nullHero.firstName}}
<!-- #enddocregion elvis-5 -->
</div>
<div>
<!-- #docregion elvis-6 -->
<!-- No hero, no problem! -->
The null hero's name is {{nullHero?.firstName}}
<!-- #enddocregion elvis-6 -->
</div>
<!-- Todo: discuss this in the Style binding section -->
<!-- enums in bindings -->
<hr><h2>Enums in binding</h2>
<p>The name of the Color.Red enum is {{Color[Color.Red]}}</p>
<p>The current color number is {{color}}</p>
<p><button [style.color]="Color[color]" (click)="colorToggle()">Enum Toggle</button>

View File

@ -0,0 +1,134 @@
import {Component, NgForm} from 'angular2/core';
import {Hero} from './hero';
import {HeroDetailComponent, BigHeroDetailComponent} from './hero-detail.component';
import {MyClickDirective, MyClickDirective2} from './my-click.directive';
// Alerter fn: monkey patch during test
export function alerter(msg?:string) {
window.alert(msg);
}
export enum Color {Red, Green, Blue};
/**
* Giant grab bag of stuff to drive the chapter
*/
@Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [
HeroDetailComponent, BigHeroDetailComponent,
MyClickDirective, MyClickDirective2
]
})
export class AppComponent {
actionName = 'Go for it';
alert = alerter;
callFax(value:string) {this.alert(`Faxing ${value} ...`)}
callPhone(value:string) {this.alert(`Calling ${value} ...`)}
canSave = true;
Color = Color;
color = Color.Red;
colorToggle() {this.color = (this.color === Color.Red)? Color.Blue : Color.Red}
currentHero = Hero.MockHeroes[0];
getStyles(el:Element){
let styles = window.getComputedStyle(el);
let showStyles = {};
for (var p in this.setStyles()){
showStyles[p] = styles[p];
}
return JSON.stringify(showStyles);
}
getVal() {return this.val};
heroes = Hero.MockHeroes;
// heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png';
// Public Domain terms of use: http://www.wpclipart.com/terms.html
heroImageUrl = 'images/hero.png';
//iconUrl = 'https://angular.io/resources/images/logos/standard/shield-large.png';
iconUrl = 'images/ng-logo.png';
isActive = false;
isSpecial = true;
isUnchanged = true;
nullHero:Hero = null; // or undefined
onCancel(event:KeyboardEvent){
let evtMsg = event ? ' Event target is '+ (<HTMLElement>event.target).innerHTML : '';
this.alert('Canceled.'+evtMsg)
}
onClickMe(event:KeyboardEvent){
let evtMsg = event ? ' Event target class is '+ (<HTMLElement>event.target).className : '';
this.alert('Click me.'+evtMsg)
}
onHeroDeleted(hero:Hero){
this.alert('Deleted hero: '+ (hero && hero.firstName))
}
onSave(event:KeyboardEvent){
let evtMsg = event ? ' Event target is '+ (<HTMLElement>event.target).innerText : '';
this.alert('Saved.'+evtMsg)
}
onSubmit(form:NgForm){
let evtMsg = form.valid ?
' Form value is '+ JSON.stringify(form.value) :
' Form is invalid';
this.alert('Form submitted.'+evtMsg)
}
product = {
name: 'frimfram',
price: 42
};
setUpperCaseFirstName(firstName:string){
//console.log(firstName);
this.currentHero.firstName = firstName.toUpperCase();
}
// #docregion setClasses
setClasses() {
return {
saveable: this.canSave, // true
modified: !this.isUnchanged, // false
special: this.isSpecial, // true
}
}
// #enddocregion setClasses
// #docregion setStyles
setStyles() {
return {
'font-style': this.canSave ? 'italic' : 'normal', // italic
'font-weight': !this.isUnchanged ? 'bold' : 'normal', // normal
'font-size': this.isSpecial ? 'x-large': 'smaller', // larger
}
}
// #enddocregion setStyles
toeChoice(picker:HTMLFieldSetElement){
let choices = picker.children;
for (let i=0; i<choices.length; i++){
var choice = <HTMLInputElement>choices[i];
if (choice.checked) {return choice.value}
}
}
title = 'Template Syntax'
val=2;
// 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
villainImageUrl = 'images/villain.png'
}

View File

@ -1,383 +0,0 @@
<!-- Interpolation and expressions</h1> -->
<h3>My First Angular Application</h3>
<h3>
{{title}}
<img src="{{heroImageUrl}}" style="height:30px">
</h3>
<p>My current hero is {{currentHero.firstName}}</p>
<div title="Hello {{currentHero.firstName}}">
Hey there, {{currentHero.firstName}}
</div>
<h3 [text-content]="'The title is '+title"></h3>
<h3>The title is {{title}}</h3>
<h3>The sum of 1 + 1 is not {{1+1+getVal()}}</h3>
<h3 id="3" #f>The element id is {{f.id}}</h3>
<hr>
<img src="{{heroImageUrl}}"/>
<img [src]="'' + heroImageUrl"/>
<h3>The title is {{title}}</h3>
<h3 [text-content]="'The title is '+title"></h3>
<!-- New Mental Model -->
<hr>
<div class="special">Mental Model</div>
<div class="special">
<!--<img src="http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png">-->
<img src="images/hero.png">
<button disabled>Save</button>
</div>
<div *ng-if="false">
<hero-detail></hero-detail>
</div>
<hr>
<!-- BAD: No Mixed Case
<h3 [textContent]="title"></h3>
-->
<!-- property over attribute -->
<!-- examine the following <img> tag in the browser tools -->
<img src="images/ng-logo.png"
[src]="heroImageUrl">
<hr>
<h3 [text-content]="title"></h3>
<hr/>
<img [src]="iconUrl"/>
<img bind-src="heroImageUrl"/>
<img [attr.src]="villainImageUrl"/>
<!-- buttons -->
<hr>
<button>Enabled</button>
<button disabled>Disabled</button>
<button disabled=false>Still disabled</button>
<hr>
<button disabled>disabled by attribute</button>
<button [disabled]="isUnchanged">disabled by property binding</button>
<button bind-disabled="isUnchanged" on-click="onSave($event)">Disabled Cancel</button>
<button [disabled]="!canSave" (click)="onSave($event)">Enabled Save</button>
<hr>
<!-- event binding -->
<button (click)="onSave()">Save</button>
<button on-click="onSave()">On Save</button>
<button (click)="onSave() || true">Save w/ propagation</button>
<button (click)="onClickMe()">Click me!</button>
<div class="parent-div" (click)="onClickMe($event)">Click me
<div class="child-div">Click me too!</div>
</div>
<click-me></click-me>
<h4>keyup loop-back component</h4>
<loop-back></loop-back>
<key-up></key-up>
<key-up2></key-up2>
<key-up3></key-up3>
<br>
<div class="box">
<little-tour></little-tour>
</div>
<!-- attribute binding -->
<hr>
<!-- any value creates the disabled attribute -->
<button [attr.disabled]="isUnchanged">Disabled</button>
<button [attr.disabled]="isUnchanged">Disabled as well</button>
<!-- lack of expression removes the attribute -->
<button disabled [attr.disabled]>Enabled</button>
<!-- create and set an aria attribute for assistive technology -->
<button [attr.aria-label]="actionName">{{actionName}} with Aria</button>
<!-- create and set a span attribute -->
<table border=1>
<tr><td>One</td><td>Two</td></tr>
<!-- ERROR: There is no `colspan` property to set!
<tr><td colspan="{{1+1}}">Three-Four</td></tr>
-->
<!-- expression calculates colspan=2 -->
<tr><td [attr.colspan]="1 + 1">Five-Six</td></tr>
</table>
<hr>
<!-- class binding -->
<hr>
<div class="special">The class is special</div>
<div [class]="'special'">The class is special</div>
<!-- toggle the "special" class on and ohf -->
<div [class.special]="isSpecial">The class binding is special</div>
<div class="special" [class.special]="!isSpecial">This one is not so special</div>
<div bind-class.special="isSpecial">This class binding is special too</div>
<!--style binding -->
<hr>
<button [style.color] = "isSpecial ? 'red' : 'green'">Red</button>
<button [style.background-color]="canSave ?'cyan' : 'grey'" >Save</button>
<button [style.font-size.em]="isSpecial ? 3 : 1" >Big</button>
<button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>
<!-- binding to a nested component -->
<hr>
<div>{{currentHero?.firstName}}</div>
<hero-detail [hero]="currentHero" (deleted)="onDeleted($event)"></hero-detail>
<!-- Two way data binding unwound;
passing the changed display value to the event handler via `$event` -->
<hr>
<input [value]="currentHero.firstName"
(input)="currentHero.firstName=$event.target.value" >
<br>
<input [(ng-model)]="currentHero.firstName">
<br>
<input
[ng-model]="currentHero.firstName"
(ng-model-change)="currentHero.firstName=$event">
<br>
<input
[ng-model]="currentHero.lastName"
(ng-model-change)="setLastName($event)">
<br>
<div>{{currentHero.fullName}}</div>
<!-- NgClass binding -->
<hr>
<div [ng-class]="isSpecial ? special : ''">This div is special</div>
<div [ng-class]="setClasses()">This div is saveable and special</div>
<div [ng-class]="setClasses()" #class-div>
After setClasses(), the classes are "{{classDiv.className}}"
</div>
<!-- NgStyle binding -->
<hr>
<div [style.font-size]="isSpecial ? 'larger' : 'smaller'" >This div is larger</div>
<div [ng-style]="setStyles()">This div is italic, normal weight, and larger</div>
<div [ng-style]="setStyles()" #class-div>
After setStyles(), the styles are "{{getStyles(classDiv)}}"
</div>
<!-- NgIf binding -->
<hr>
<div><b>NgIf Binding</b></div>
<div *ng-if="currentHero">Add {{currentHero.firstName}}</div>
<div *ng-if="nullHero">Remove {{nullHero.firstName}}</div>
<div>Hero Detail removed from DOM because isActive is false</div>
<hero-detail *ng-if="isActive" [hero]="currentHero"></hero-detail>
<!-- NgIf binding with template (no *) -->
<template [ng-if]="currentHero">Add {{currentHero.firstName}} with template</template>
<!-- Does not show because isActive is false! -->
<div>Hero Detail removed from DOM (via template) because isActive is false</div>
<template [ng-if]="isActive">
<hero-detail [hero]="currentHero"></hero-detail>
</template>
<!-- isSpecial is true -->
<div [class.hidden]="!isSpecial">Show with class</div>
<div [class.hidden]="isSpecial">Hide with class</div>
<hero-detail [class.hidden]="isSpecial" [hero]="currentHero"></hero-detail>
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
<!-- NgSwitch binding -->
<hr>
<div><b>NgSwitch Binding</b></div>
<fieldset #toe-picker (click)="null" >
<input type="radio" name="toes" value="Eenie">Eenie
<input type="radio" name="toes" checked value="Meanie">Meanie
<input type="radio" name="toes" value="Miney">Miney
<input type="radio" name="toes" value="Moe">Moe
<input type="radio" name="toes" value="???">???
</fieldset>
<div class="toe">You picked
<span [ng-switch]="toeChoice(toePicker)">
<template [ng-switch-when]="'Eenie'">Eenie</template>
<template [ng-switch-when]="'Meanie'">Meanie</template>
<template [ng-switch-when]="'Miney'">Miney</template>
<template [ng-switch-when]="'Moe'">Moe</template>
<template ng-switch-default>Other</template>
</span>
</div>
<!-- NgFor binding -->
<hr>
<div><b>NgFor Binding</b></div>
<br>
<div class="box">
<!-- *ng-for of div w/ interpolation -->
<div *ng-for="#hero of heroes">{{hero.fullName}}</div>
</div>
<br>
<div class="box">
<!-- *ng-for of div w/ interpolation -->
<!-- Ex: 1 - Hercules Son of Zeus -->
<div *ng-for="#hero of heroes, #i=index">{{i+1}} - {{hero.fullName}}</div>
</div>
<br>
<div class="box">
<!-- *ng-for w/ little-hero Component -->
<little-hero *ng-for="#hero of heroes" [hero]="hero"></little-hero>
</div>
<br>
<div class="box">
<!-- ng-for w/ little-hero Component and a template "attribute" directive -->
<little-hero template="ng-for #hero of heroes" [hero]="hero"></little-hero>
</div>
<br>
<div class="box">
<!-- ng-for w/ little-hero Component inside a template element -->
<template ng-for #hero [ng-for-of]="heroes">
<little-hero [hero]="hero"></little-hero>
</template>
</div>
<!-- Pipe operator -->
<hr>
<!-- Force title to uppercase -->
<div>{{ title | uppercase }}</div>
<!-- Pipe chaining: force title to uppercase, then to lowercase -->
<div>{{ title | uppercase | lowercase }}</div>
<!-- pipe with configuration argument -->
<div>Birthdate: {{currentHero?.birthdate | date:'longDate'}}</div>
<div>Birthdate: {{(currentHero?.birthdate | date:'longDate') | uppercase}}</div>
<div>
<!-- pipe price to USD and display the $ symbol -->
<label>Price: </label>{{product.price | currency:'USD':true}}
</div>
<!-- Null values and the Elvis operator -->
<hr>
<div>The title is {{ title }}</div>
<div>The current hero's name is {{currentHero?.firstName}}</div>
<div>The current hero's name is {{currentHero.firstName}}</div>
<!--
<div>The null hero's name is {{nullHero.firstName}}</div>
See console log
TypeError: Cannot read property 'firstName' of null in [null]
-->
<!--No hero, div not displayed, no error -->
<div *ng-if="nullHero">The null hero's name is {{nullHero?.firstName}}</div>
<!--guard in the expression, no display, no error
[FAILS No short-circuiting of logical operators]
<div>The null hero's name is {{nullHero && nullHero.firstName}}</div>
-->
<!-- No hero, no problem! -->
<div>The null hero's name is {{nullHero?.firstName}}</div>
<!-- template local variable -->
<hr>
<h3>Template Driven Form</h3>
<form (ng-submit)="onSubmit(hf)" #hf="form">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required
ng-control="firstName"
[(ng-model)]="currentHero.firstName">
</div>
<button type="submit" [disabled]="!hf.form.valid">Submit</button>
</form>
<hr>
<!-- btn refers to the button element; show its disabled state -->
<button #btn disabled [text-content]="'disabled by attribute: '+btn.disabled"></button>
<!-- phone refers to the input element; pass its `value` to an event handler -->
<input #phone placeholder="phone number">
<button (click)="callPhone(phone.value)">Call</button>
<!-- ohficFax refers to the input element; pass its `value` to an event handler -->
<input var-ohfice-fax placeholder="phone number">
<button (click)="callFax(ohficeFax.value)">Fax</button>
<!-- enums in bindings -->
<hr>
<h2>Enums in bindings </h2>
<p>The name of the Color.Red enum is {{Color[Color.Red]}}</p>
<p>The current color number is {{color}}</p>
<p><button [style.color]="Color[color]" (click)="colorToggle()">Enum Toggle</button>

View File

@ -1,299 +0,0 @@
// NOT EVERYTHING IS NEEDED BY TEMPLATE-SYNTAX CHAPTER
// Much left-over from support for "User Input" chapter such as
// ClickMeComponent,
// KeyUpComponent, KeyUpComponentV2, KeyUpComponentV3,
// LittleTour, LoopbackComponent,
// TODO: purge extraneous material
/// #docplaster
import {bootstrap, Component, CORE_DIRECTIVES,
Input, Output,
Directive,
ElementRef, EventEmitter,
NgForm, FORM_DIRECTIVES
} from 'angular2/angular2';
class Hero {
public id:number
constructor(
public firstName:string,
public lastName?:string,
public birthdate?:Date,
public url?:string,
public rate:number = 100) {
this.id = Hero.nextId++;
}
get fullName() {return `${this.firstName} ${this.lastName}`;}
static nextId = 1;
static MockHeroes = [
new Hero(
'Hercules',
'Son of Zeus',
new Date(1970, 1, 25),
'http://www.imdb.com/title/tt0065832/',
325),
new Hero('eenie', 'toe'),
new Hero('Meanie', 'Toe'),
new Hero('Miny', 'Toe'),
new Hero('Moe', 'Toe')
];
}
// for fun; not used (yet)
@Directive({selector: 'select'})
class DecoratorDirective {
constructor(el: ElementRef){
console.log(el)
}
}
@Component({
selector: 'hero-detail',
/*
inputs: ['hero'],
outputs: ['deleted'],
*/
template: `
<div style="border: 1px solid black; padding:3px">
<div><b>Hero Detail: {{hero?.fullName}}</b></div>
<div>First: {{hero?.firstName}}</div>
<div>Last: {{hero?.lastName}}</div>
<div>Birthdate: {{hero?.birthdate | date:'longDate'}}</div>
<div>Web: <a href="{{hero?.url}}" target="_blank">{{hero?.url}}</a></div>
<div>Rate/hr: {{hero?.rate | currency:'EUR'}}</div>
<button (click)="onDelete()">Delete</button>
</div>
`
})
class HeroDetailComponent {
@Input()
hero: Hero;
@Output()
deleted = new EventEmitter<Hero>();
onDelete() {
this.deleted.next(this.hero);
}
}
@Component({
selector: 'little-hero',
template: '<div>{{hero?.fullName}}</div>'
})
class LittleHeroComponent {
@Input()
hero: Hero;
}
@Component({
selector: 'click-me',
template: '<button (click)="onClickMe()">Click me</button>'
})
class ClickMeComponent {
onClickMe(){
alert('You are my hero!')
}
}
@Component({
selector: 'loop-back',
template: '<input #box (keyup)="0"> <p>{{box.value}}</p>'
})
class LoopbackComponent {
}
@Component({
selector: 'key-up',
template: `
<h4>Give me some keys!</h4>
<div><input (keyup)="onKey($event)"><div>
<div>{{values}}</div>
`
})
class KeyUpComponent {
values='';
onKey(event:KeyboardEvent) {
this.values += (<HTMLInputElement>event.target).value + ' | ';
}
}
@Component({
selector: 'key-up2',
template: `
<h4>Give me some more keys!</h4>
<div><input #box (keyup)="onKey(box.value)"><div>
<div>{{values}}</div>
`
})
class KeyUpComponentV2 {
values='';
onKey(value:string) {
this.values += value + ' | ';
}
}
@Component({
selector: 'key-up3',
template: `
<h4>Type away! Press [enter] when done.</h4>
<div><input #box (keyup.enter)="values=box.value"><div>
<div>{{values}}</div>
`
})
class KeyUpComponentV3 {
values='';
}
@Component({
selector: 'little-tour',
template: `
<h4>Little Tour of Heroes</h4>
<input #box
(keyup.enter)="addHero(box.value)"
(blur)="addHero(box.value)">
<button (click)=addHero(box.value)>Add</button>
<ul><li *ng-for="#hero of heroes">{{hero}}</li></ul>
`,
directives: [CORE_DIRECTIVES]
})
class LittleTour {
heroes=['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
addHero(newHero:string) {
if (newHero) {
this.heroes.push(newHero);
newHero = null; // clear the newHero textbox
}
}
}
bootstrap(LittleTour);
enum Color {Red, Green, Blue};
@Component({
selector: 'my-app',
templateUrl: 'app/app.html',
directives: [
CORE_DIRECTIVES, FORM_DIRECTIVES,
ClickMeComponent,
KeyUpComponent, KeyUpComponentV2, KeyUpComponentV3,
LittleTour, LoopbackComponent,
HeroDetailComponent, LittleHeroComponent
]
})
class AppComponent {
actionName = 'Go for it';
callFax(value:string) {alert(`Faxing ${value} ...`)}
callPhone(value:string) {alert(`Calling ${value} ...`)}
canSave = true;
Color = Color;
color = Color.Red;
colorToggle() {this.color = (this.color === Color.Red)? Color.Blue : Color.Red}
currentHero = Hero.MockHeroes[0];
getStyles(el:Element){
let styles = window.getComputedStyle(el);
let showStyles = {};
for (var p in this.setStyles()){
showStyles[p] = styles[p];
}
return JSON.stringify(showStyles);
}
getVal() {return this.val};
heroes = Hero.MockHeroes;
//heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png';
heroImageUrl = 'images/hero.png';
//iconUrl = 'https://angular.io/resources/images/logos/standard/shield-large.png';
iconUrl = 'images/ng-logo.png';
isActive = false;
isSpecial = true;
isUnchanged = true;
nullHero:Hero = null; // or undefined
onCancel(event:KeyboardEvent){
let evtMsg = event ? ' Event target is '+ (<HTMLElement>event.target).innerHTML : '';
alert('Canceled.'+evtMsg)
}
onClickMe(event:KeyboardEvent){
let evtMsg = event ? ' Event target class is '+ (<HTMLElement>event.target).className : '';
alert('Click me.'+evtMsg)
}
onDeleted(hero:Hero){
alert('Deleted hero: '+ (hero && hero.firstName))
}
onSave(event:KeyboardEvent){
let evtMsg = event ? ' Event target is '+ (<HTMLElement>event.target).innerText : '';
alert('Saved.'+evtMsg)
}
onSubmit(form:NgForm){
let evtMsg = form.valid ?
' Form value is '+ JSON.stringify(form.value) :
' Form is invalid';
alert('Form submitted.'+evtMsg)
}
product = {
name: 'frimfram',
price: 42
};
setLastName(lastName:string){
console.log(lastName);
this.currentHero.lastName = lastName;
}
setClasses() {
return {
saveable: this.canSave, // true
modified: !this.isUnchanged, // false
special: this.isSpecial, // true
}
}
setStyles() {
return {
'font-style': this.canSave ? 'italic' : 'normal', // italic
'font-weight': !this.isUnchanged ? 'bold' : 'normal', // normal
'font-size': this.isSpecial ? 'larger' : 'smaller', // larger
}
}
toeChoice(picker:HTMLFieldSetElement){
let choices = picker.children;
for (let i=0; i<choices.length; i++){
var choice = <HTMLInputElement>choices[i];
if (choice.checked) {return choice.value}
}
}
title = 'Template Syntax'
val=2;
// villainImageUrl = 'http://www.clker.com/cliparts/u/s/y/L/x/9/villain-man-hi.png'
villainImageUrl = 'images/villain.png'
}
bootstrap(AppComponent);

View File

@ -0,0 +1,3 @@
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
bootstrap(AppComponent);

View File

@ -0,0 +1,11 @@
// Useful for spying on an element
// for fun; not used (yet)
import {Directive, ElementRef} from 'angular2/core';
// set the selector for the element type to spy on.
@Directive({selector: 'select'})
export class DecoratorDirective {
constructor(el: ElementRef){
console.log(el)
}
}

View File

@ -0,0 +1,70 @@
import {Component, Input, Output, EventEmitter} from 'angular2/core';
import {Hero} from './hero';
let nextHeroDetailId = 1;
// #docregion input-output-2
@Component({
// #enddocregion input-output-2
selector: 'hero-detail',
// #docregion input-output-2
inputs: ['hero'],
outputs: ['deleted'],
// #enddocregion input-output-2
template: `
<div id="lh{{id}}">
{{hero?.fullName}}
<img src="{{heroImageUrl}}" style="height:24px">
<a href="#lh{{id}}" (click)="onDelete()">delete</a>
</div>`
// #docregion input-output-2
})
// #enddocregion input-output-2
export class HeroDetailComponent {
hero: Hero;
// #docregion deleted
deleted = new EventEmitter<Hero>();
onDelete() {
this.deleted.emit(this.hero);
}
// #enddocregion
// heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png';
// Public Domain terms of use: http://www.wpclipart.com/terms.html
heroImageUrl = 'images/hero.png';
id = nextHeroDetailId++;
}
@Component({
selector: 'big-hero-detail',
/*
inputs: ['hero'],
outputs: ['deleted'],
*/
template: `
<div style="border: 1px solid black; padding:3px">
<img src="{{heroImageUrl}}" style="float:left; margin-right:8px;">
<div><b>{{hero?.fullName}}</b></div>
<div>First: {{hero?.firstName}}</div>
<div>Last: {{hero?.lastName}}</div>
<div>Birthdate: {{hero?.birthdate | date:'longDate'}}</div>
<div>Web: <a href="{{hero?.url}}" target="_blank">{{hero?.url}}</a></div>
<div>Rate/hr: {{hero?.rate | currency:'EUR'}}</div>
<br clear="all">
<button (click)="onDelete()">Delete</button>
</div>
`
})
export class BigHeroDetailComponent extends HeroDetailComponent {
// #docregion input-output-1
@Input() hero: Hero;
@Output() deleted = new EventEmitter<Hero>();
// #enddocregion input-output-1
onDelete() {
this.deleted.emit(this.hero);
}
}

View File

@ -0,0 +1,30 @@
export class Hero {
public id:number
constructor(
public firstName:string,
public lastName?:string,
public birthdate?:Date,
public url?:string,
public rate:number = 100) {
this.id = Hero.nextId++;
}
get fullName() {return `${this.firstName} ${this.lastName}`;}
static nextId = 1;
static MockHeroes = [
new Hero(
'Hercules',
'Son of Zeus',
new Date(1970, 1, 25),
'http://www.imdb.com/title/tt0065832/',
325),
new Hero('eenie', 'toe'),
new Hero('Meanie', 'Toe'),
new Hero('Miny', 'Toe'),
new Hero('Moe', 'Toe')
];
}

View File

@ -0,0 +1,32 @@
import {Directive, Output, ElementRef, EventEmitter} from 'angular2/core';
@Directive({selector:'[my-click]'})
export class MyClickDirective {
// #docregion my-click-output-1
@Output('myClick') clicks = new EventEmitter<string>();
// #enddocregion my-click-output-1
constructor(el: ElementRef){
el.nativeElement
.addEventListener('click', (event:Event) => {
this.clicks.emit('Click!');
});
}
}
// #docregion my-click-output-2
@Directive({
// #enddocregion my-click-output-2
selector:'[my-click2]',
// #docregion my-click-output-2
outputs:['clicks:myClick']
})
// #enddocregion my-click-output-2
export class MyClickDirective2 {
clicks = new EventEmitter<string>();
constructor(el: ElementRef){
el.nativeElement
.addEventListener('click', (event:Event) => {
this.clicks.emit('Click!');
});
}
}

View File

@ -9,14 +9,12 @@
System.config({ System.config({
packages: {'app': {defaultExtension: 'js'}} packages: {'app': {defaultExtension: 'js'}}
}); });
System.import('app/app'); System.import('app/boot');
</script> </script>
</head> </head>
<body> <body>
<my-app>Loading...</my-app> <my-app>Loading...</my-app>
<hr>
<little-tour>Loading...</little-tour>
</body> </body>
</html> </html>

View File

@ -4,6 +4,8 @@ img {height: 100px;}
.child-div {margin-left: 1em; font-weight: normal} .child-div {margin-left: 1em; font-weight: normal}
.hidden {display: none} .hidden {display: none}
.parent-div {margin-top: 1em; font-weight: bold} .parent-div {margin-top: 1em; font-weight: bold}
.special {font-weight:bold;} .special {font-weight:bold; font-size: x-large}
.bad {color: red;}
.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 }

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@ include ../../../../_includes/_util-fns
we want to know about it. These user actions all raise DOM events. we want to know about it. These user actions all raise DOM events.
In this chapter we learn to bind to those events using the Angular Event Binding syntax. In this chapter we learn to bind to those events using the Angular Event Binding syntax.
[Live Example](/resources/live-examples/user-input/ts/src/plnkr.html).
:marked :marked
## Binding to User Input Events ## Binding to User Input Events

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB