@@ -11,11 +11,11 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"angular2": "2.0.0-alpha.46",
|
||||
"systemjs": "0.19.2"
|
||||
"angular2": "2.0.0-alpha.48",
|
||||
"systemjs": "0.19.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"live-server": "^0.8.1",
|
||||
"typescript": "^1.6.2"
|
||||
"typescript": "^1.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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'
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
@@ -0,0 +1,3 @@
|
||||
import {bootstrap} from 'angular2/platform/browser';
|
||||
import {AppComponent} from './app.component';
|
||||
bootstrap(AppComponent);
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
];
|
||||
}
|
||||
@@ -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!');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Template Syntax</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<script src="../node_modules/systemjs/dist/system.src.js"></script>
|
||||
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
|
||||
<script>
|
||||
System.config({
|
||||
packages: {'app': {defaultExtension: 'js'}}
|
||||
});
|
||||
System.import('app/app');
|
||||
System.import('app/boot');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<my-app>Loading...</my-app>
|
||||
<hr>
|
||||
<little-tour>Loading...</little-tour>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -4,6 +4,8 @@ img {height: 100px;}
|
||||
.child-div {margin-left: 1em; font-weight: normal}
|
||||
.hidden {display: none}
|
||||
.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;}
|
||||
little-hero {color:blue; font-size: smaller; background-color: Turquoise }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,8 @@ include ../../../../_includes/_util-fns
|
||||
When the user clicks a link, pushes a button, or types on the keyboard
|
||||
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.
|
||||
|
||||
[Live Example](/resources/live-examples/user-input/ts/src/plnkr.html).
|
||||
|
||||
:marked
|
||||
## Binding to User Input Events
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
Reference in New Issue
Block a user