(docs) User Input - refactored to its own example and support blur event
This commit is contained in:
parent
dd0d44eb93
commit
c4416cfb2c
|
@ -78,9 +78,7 @@
|
|||
<button on-click="onSave()">On Save</button>
|
||||
<button (click)="onSave() || true">Save w/ propagation</button>
|
||||
|
||||
<!-- #docregion click-me-button -->
|
||||
<button (click)="onClickMe()">Click me!</button>
|
||||
<!-- #enddocregion click-me-button -->
|
||||
|
||||
<div class="parent-div" (click)="onClickMe($event)">Click me
|
||||
<div class="child-div">Click me too!</div>
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
//**** Referenced in template-syntax and user-input chapters
|
||||
// #docplaster
|
||||
// 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
|
||||
|
||||
// imports formatted for dev guide only
|
||||
// #docregion little-tour-of-heroes-app
|
||||
import {bootstrap, Component, CORE_DIRECTIVES} from 'angular2/angular2';
|
||||
|
||||
// #enddocregion little-tour-of-heroes-app
|
||||
/// #docplaster
|
||||
|
||||
import {
|
||||
import {bootstrap, Component, CORE_DIRECTIVES,
|
||||
Input, Output,
|
||||
Directive,
|
||||
ElementRef, EventEmitter,
|
||||
|
@ -93,7 +94,6 @@ class LittleHeroComponent {
|
|||
hero: Hero;
|
||||
}
|
||||
|
||||
// #docregion click-me-component
|
||||
@Component({
|
||||
selector: 'click-me',
|
||||
template: '<button (click)="onClickMe()">Click me</button>'
|
||||
|
@ -103,18 +103,14 @@ class ClickMeComponent {
|
|||
alert('You are my hero!')
|
||||
}
|
||||
}
|
||||
// #enddocregion click-me-component
|
||||
|
||||
// #docregion loop-back-component
|
||||
@Component({
|
||||
selector: 'loop-back',
|
||||
template: '<input #box (keyup)="0"> <p>{{box.value}}</p>'
|
||||
})
|
||||
class LoopbackComponent {
|
||||
}
|
||||
// #enddocregion loop-back-component
|
||||
|
||||
// #docregion key-up-component
|
||||
@Component({
|
||||
selector: 'key-up',
|
||||
template: `
|
||||
|
@ -129,9 +125,7 @@ class KeyUpComponent {
|
|||
this.values += event.target.value + ' | ';
|
||||
}
|
||||
}
|
||||
// #enddocregion key-up-component
|
||||
|
||||
// #docregion key-up2-component
|
||||
@Component({
|
||||
selector: 'key-up2',
|
||||
template: `
|
||||
|
@ -146,10 +140,7 @@ class KeyUpComponentV2 {
|
|||
this.values += value + ' | ';
|
||||
}
|
||||
}
|
||||
// #enddocregion key-up2-component
|
||||
|
||||
|
||||
// #docregion key-up3-component
|
||||
@Component({
|
||||
selector: 'key-up3',
|
||||
template: `
|
||||
|
@ -161,10 +152,7 @@ class KeyUpComponentV2 {
|
|||
class KeyUpComponentV3 {
|
||||
values='';
|
||||
}
|
||||
// #enddocregion key-up3-component
|
||||
|
||||
// #docregion little-tour-of-heroes-app
|
||||
// #docregion little-tour-of-heroes-component
|
||||
@Component({
|
||||
selector: 'little-tour',
|
||||
template: `
|
||||
|
@ -185,10 +173,8 @@ class LittleTour {
|
|||
}
|
||||
}
|
||||
}
|
||||
// #enddocregion little-tour-of-heroes-component
|
||||
|
||||
bootstrap(LittleTour);
|
||||
// #enddocregion little-tour-of-heroes-app
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
src/**/*.js
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "angular2-template-syntax",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"tsc": "tsc -p src -w",
|
||||
"start": "live-server --open=src"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"angular2": "2.0.0-alpha.44",
|
||||
"systemjs": "0.19.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"live-server": "^0.8.1",
|
||||
"typescript": "^1.6.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<!-- #docregion click-me-button -->
|
||||
<button (click)="onClickMe()">Click me!</button>
|
||||
<!-- #enddocregion click-me-button -->
|
||||
|
||||
<h4>keyup loop-back component</h4>
|
||||
<loop-back></loop-back>
|
||||
|
||||
<key-up></key-up>
|
||||
|
||||
<key-up2></key-up2>
|
||||
|
||||
<key-up3></key-up3>
|
||||
|
||||
<key-up4></key-up4>
|
|
@ -0,0 +1,147 @@
|
|||
// #docplaster
|
||||
|
||||
// imports formatted for dev guide only
|
||||
// #docregion little-tour-of-heroes-app
|
||||
import {bootstrap, Component, CORE_DIRECTIVES} from 'angular2/angular2';
|
||||
|
||||
// #enddocregion little-tour-of-heroes-app
|
||||
|
||||
|
||||
// #docregion click-me-component
|
||||
@Component({
|
||||
selector: 'click-me',
|
||||
template: '<button (click)="onClickMe()">Click me</button>'
|
||||
})
|
||||
class ClickMeComponent {
|
||||
onClickMe(){
|
||||
alert('You are my hero!')
|
||||
}
|
||||
}
|
||||
// #enddocregion click-me-component
|
||||
|
||||
// #docregion loop-back-component
|
||||
@Component({
|
||||
selector: 'loop-back',
|
||||
template: '<input #box (keyup)="0"> <p>{{box.value}}</p>'
|
||||
})
|
||||
class LoopbackComponent {
|
||||
}
|
||||
// #enddocregion loop-back-component
|
||||
|
||||
// #docregion key-up-component
|
||||
@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) {
|
||||
this.values += event.target.value + ' | ';
|
||||
}
|
||||
}
|
||||
// #enddocregion key-up-component
|
||||
|
||||
// #docregion key-up2-component
|
||||
@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) {
|
||||
this.values += value + ' | ';
|
||||
}
|
||||
}
|
||||
// #enddocregion key-up2-component
|
||||
|
||||
|
||||
// #docregion key-up3-component
|
||||
@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='';
|
||||
}
|
||||
// #enddocregion key-up3-component
|
||||
|
||||
|
||||
// #docregion key-up4-component
|
||||
@Component({
|
||||
selector: 'key-up4',
|
||||
template: `
|
||||
<h4>Type away! Press [enter] or mouse away when done.</h4>
|
||||
<div>
|
||||
<input #box
|
||||
(keyup.enter)="values=box.value"
|
||||
(blur)="values=box.value">
|
||||
<div>
|
||||
<div>{{values}}</div>
|
||||
`
|
||||
})
|
||||
class KeyUpComponentV4 {
|
||||
values='';
|
||||
}
|
||||
// #enddocregion key-up4-component
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
templateUrl: 'app/app.html',
|
||||
directives: [
|
||||
CORE_DIRECTIVES,
|
||||
ClickMeComponent,
|
||||
KeyUpComponent, KeyUpComponentV2, KeyUpComponentV3, KeyUpComponentV4,
|
||||
LoopbackComponent,
|
||||
]
|
||||
})
|
||||
class AppComponent {
|
||||
|
||||
onClickMe(event){
|
||||
let evtMsg = event ? ' Event target class is '+ event.target.className : '';
|
||||
alert('Click me.'+evtMsg)
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap(AppComponent);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
// #docregion little-tour-of-heroes-app
|
||||
@Component({
|
||||
selector: 'little-tour',
|
||||
template: `
|
||||
<h4>Little Tour of Heroes</h4>
|
||||
<input #new-hero
|
||||
(keyup.enter)="addHero(newHero)"
|
||||
(blur)="addHero(newHero)">
|
||||
<button (click)=addHero(newHero)>Add</button>
|
||||
<ul><li *ng-for="#hero of heroes">{{hero}}</li></ul>
|
||||
`,
|
||||
directives: [CORE_DIRECTIVES]
|
||||
})
|
||||
class LittleTour {
|
||||
heroes=['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
|
||||
|
||||
addHero(newHero) {
|
||||
if (newHero.value) {
|
||||
this.heroes.push(newHero.value);
|
||||
newHero.value = null; // clear the newHero textbox
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap(LittleTour);
|
||||
// #enddocregion little-tour-of-heroes-app
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>User Input</title>
|
||||
<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');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<my-app>Loading...</my-app>
|
||||
<hr>
|
||||
<little-tour>Loading...</little-tour>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
fieldset {border-style:none}
|
||||
img {height: 100px;}
|
||||
.box {border: 1px solid black; padding:3px}
|
||||
.child-div {margin-left: 1em; font-weight: normal}
|
||||
.hidden {display: none}
|
||||
.parent-div {margin-top: 1em; font-weight: bold}
|
||||
.special {font-weight:bold;}
|
||||
.toe {margin-left: 1em; font-style: italic;}
|
||||
little-hero {color:blue; font-size: smaller; background-color: Turquoise }
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES5",
|
||||
"module": "commonjs",
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"removeComments": false,
|
||||
"noImplicitAny": false
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ include ../../../../_includes/_util-fns
|
|||
|
||||
The syntax is simple. We assign a template expression to the DOM event name, surrounded in parentheses.
|
||||
A click Event Binding makes for a quick illustration.
|
||||
+makeExample('template-syntax/ts/src/app/app.html', 'click-me-button')(format=".")
|
||||
+makeExample('user-input/ts/src/app/app.html', 'click-me-button')(format=".")
|
||||
|
||||
:markdown
|
||||
The `(click)` to the left of the equal sign identifies the button's click event as the **target of the binding**.
|
||||
|
@ -28,7 +28,7 @@ include ../../../../_includes/_util-fns
|
|||
<!--
|
||||
These sample can be found in http://plnkr.co/edit/mr63T5
|
||||
-->
|
||||
+makeExample('template-syntax/ts/src/app/app.ts', 'click-me-component')
|
||||
+makeExample('user-input/ts/src/app/app.ts', 'click-me-component')
|
||||
:markdown
|
||||
The `onClickMe` in the template refers to the `onClickMe` method of the component.
|
||||
When the user clicks the button, Angular calls the component's `onClickMe` method.
|
||||
|
@ -40,7 +40,7 @@ include ../../../../_includes/_util-fns
|
|||
what the user types back onto the screen.
|
||||
|
||||
This time we'll both listen to an event and grab the user's input.
|
||||
+makeExample('template-syntax/ts/src/app/app.ts', 'key-up-component')
|
||||
+makeExample('user-input/ts/src/app/app.ts', 'key-up-component')
|
||||
:markdown
|
||||
Angular makes an event object available in the **`$event`** variable. The user data we want is in that variable somewhere.
|
||||
|
||||
|
@ -72,7 +72,7 @@ code-example().
|
|||
|
||||
Let's demonstrate with a clever keystroke loopback in a single line of template HTML.
|
||||
We don't actually need a dedicated component to do this but we'll make one anyway.
|
||||
+makeExample('template-syntax/ts/src/app/app.ts', 'loop-back-component')
|
||||
+makeExample('user-input/ts/src/app/app.ts', 'loop-back-component')
|
||||
:markdown
|
||||
We've declared a template local variable named `box` on the `<input>` element.
|
||||
The `box` variable is a reference to the `<input>` element itself which means we can
|
||||
|
@ -91,7 +91,7 @@ code-example().
|
|||
That local template variable is intriguing. It's clearly easer to get to the textbox with that
|
||||
variable than to go through the `$event` object. Maybe we can re-write our previous
|
||||
"key-up" example using the variable to acquire the user's' input. Let's give it a try.
|
||||
+makeExample('template-syntax/ts/src/app/app.ts', 'key-up2-component')
|
||||
+makeExample('user-input/ts/src/app/app.ts', 'key-up2-component')
|
||||
:markdown
|
||||
That sure seems easier.
|
||||
An especially nice aspect of this approach is that our component code gets clean data values from the view.
|
||||
|
@ -112,12 +112,20 @@ code-example().
|
|||
Only then do we update the component's `values` property ...
|
||||
inside the event expression rather than in the component ...
|
||||
because we can ... even if it is a dubious practice.
|
||||
+makeExample('template-syntax/ts/src/app/app.ts', 'key-up3-component')
|
||||
.alert.is-helpful
|
||||
:markdown
|
||||
We won't transfer the current state of the input box if the user mouses away or clicks
|
||||
+makeExample('user-input/ts/src/app/app.ts', 'key-up3-component')
|
||||
|
||||
.l-main-section
|
||||
:markdown
|
||||
## On blur
|
||||
|
||||
Our previous example won't transfer the current state of the input box if the user mouses away and clicks
|
||||
elsewhere on the page. We only update the component's `values` property when the user presses "Enter"
|
||||
inside the input box.
|
||||
|
||||
Let's fix that by listening to the input box's blur event as well.
|
||||
|
||||
+makeExample('user-input/ts/src/app/app.ts', 'key-up4-component')
|
||||
|
||||
.l-main-section
|
||||
:markdown
|
||||
## Put it all together
|
||||
|
@ -125,7 +133,9 @@ code-example().
|
|||
We've acquired a small arsenal of event binding techniques in this chapter.
|
||||
|
||||
Let's put it all together in a micro-app
|
||||
that can display a list of heroes and add new heroes to that list.
|
||||
that can display a list of heroes and add new heroes to that list
|
||||
by typing in the input box and hitting "Enter", clicking "Add", or clicking
|
||||
elsewhere on the page.
|
||||
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/user-input/little-tour.png' alt="Little Tour of Heroes")
|
||||
|
@ -135,7 +145,7 @@ figure.image-display
|
|||
<!--
|
||||
This example in http://plnkr.co/edit/JWeIqq
|
||||
-->
|
||||
+makeExample('template-syntax/ts/src/app/app.ts', 'little-tour-of-heroes-app')
|
||||
+makeExample('user-input/ts/src/app/app.ts', 'little-tour-of-heroes-app')
|
||||
:markdown
|
||||
We've seen almost everything here before. A few things are new or bear repeating.
|
||||
|
||||
|
@ -149,11 +159,6 @@ figure.image-display
|
|||
The Angular workaround is to spell the declaration in "snake case". Angular translates "#new-hero"
|
||||
to `newHero` for template expressions ... which is exactly what we want.
|
||||
|
||||
### **keyup.enter filter**
|
||||
We'll add a hero when the user clicks the "Add" button or hits the "Enter" key. We ignore all other keys.
|
||||
We accept that we might lose the new hero if the user clicks elsewhere or leaves the page
|
||||
without having hit "Enter" or the "Add" button first. Let's hope the users don't complain.
|
||||
|
||||
### **newHero refers to the `<input>` element**
|
||||
We can access the `newHero` variable from any sibling or child of the `<input>` element.
|
||||
When the user clicks the button, we don't need a fancy css selector to
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 15 KiB |
Loading…
Reference in New Issue