parent
f4acc0ccbc
commit
fe0f8086f4
@ -4,7 +4,7 @@ include ../../../../_includes/_util-fns
|
|||||||
When the user clicks a link, pushes a button, or types on the keyboard
|
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.
|
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/plnkr.html).
|
[Live Example](/resources/live-examples/user-input/ts/plnkr.html).
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
@ -25,7 +25,7 @@ include ../../../../_includes/_util-fns
|
|||||||
of JavaScript with a few added tricks.
|
of JavaScript with a few added tricks.
|
||||||
|
|
||||||
When writing a binding we must be aware of a template expression's **execution context**.
|
When writing a binding we must be aware of a template expression's **execution context**.
|
||||||
The identifers appearing within an expression belong to a specific context object.
|
The identifiers appearing within an expression belong to a specific context object.
|
||||||
That object is usually the Angular component that controls the template ... which it definitely is
|
That object is usually the Angular component that controls the template ... which it definitely is
|
||||||
in this case because that snippet of HTML belongs to the following component:
|
in this case because that snippet of HTML belongs to the following component:
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ include ../../../../_includes/_util-fns
|
|||||||
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-template', 'app/keyup.components.ts (template v.1)')
|
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-template', 'app/keyup.components.ts (template v.1)')
|
||||||
:marked
|
:marked
|
||||||
Angular makes an event object available in the **`$event`** variable
|
Angular makes an event object available in the **`$event`** variable
|
||||||
which we pass to the component's `onKey()` method.
|
which we pass to the component's `onKey()` method.
|
||||||
The user data we want is in that variable somewhere.
|
The user data we want is in that variable somewhere.
|
||||||
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class-no-type', 'app/keyup.components.ts (class v.1)')
|
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class-no-type', 'app/keyup.components.ts (class v.1)')
|
||||||
:marked
|
:marked
|
||||||
@ -54,8 +54,8 @@ include ../../../../_includes/_util-fns
|
|||||||
[`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement) which
|
[`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement) which
|
||||||
has a `value` property and that's where we find our user input data.
|
has a `value` property and that's where we find our user input data.
|
||||||
|
|
||||||
With had this in mind when we passed `$event` to our `onKey()` component method where we extract the user's input and
|
We had this in mind when we passed `$event` to our `onKey()` component method. This is where we extract the user's input and
|
||||||
concatenate it to the previous user data that we're accumulating in the component's' `values` property.
|
concatenate it to the previous user data that we're accumulating in the component's `values` property.
|
||||||
We then use [interpolation](./template-syntax.html#interpolation)
|
We then use [interpolation](./template-syntax.html#interpolation)
|
||||||
to display the accumulating `values` property back on screen.
|
to display the accumulating `values` property back on screen.
|
||||||
|
|
||||||
@ -73,9 +73,9 @@ figure.image-display
|
|||||||
We can rewrite the method, casting to HTML DOM objects like this.
|
We can rewrite the method, casting to HTML DOM objects like this.
|
||||||
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class', 'app/keyup.components.ts (class v.1 - strongly typed )')
|
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class', 'app/keyup.components.ts (class v.1 - strongly typed )')
|
||||||
:marked
|
:marked
|
||||||
<br>Strong typing reveals a serious problem with passing a DOM event into the method:
|
<br>Strong typing reveals a serious problem with passing a DOM event into the method:
|
||||||
too much awareness of template details, too little separation of concerns.
|
too much awareness of template details, too little separation of concerns.
|
||||||
|
|
||||||
We'll address this problem in our next try at processing user keystrokes.
|
We'll address this problem in our next try at processing user keystrokes.
|
||||||
:marked
|
:marked
|
||||||
|
|
||||||
@ -84,31 +84,31 @@ figure.image-display
|
|||||||
## Get user input from a local template variable
|
## Get user input from a local template variable
|
||||||
There's another way to get the user data without the `$event` variable.
|
There's another way to get the user data without the `$event` variable.
|
||||||
|
|
||||||
Angular has syntax feature called [**local template variables**](./template-syntax.html#local-vars).
|
Angular has a syntax feature called [**local template variables**](./template-syntax.html#local-vars).
|
||||||
These variables grant us direct access to an element.
|
These variables grant us direct access to an element.
|
||||||
We declare a local template variable by preceding an identifier with a hash/pound character (#).
|
We declare a local template variable by preceding an identifier with a hash/pound character (#).
|
||||||
|
|
||||||
Let's demonstrate with a clever keystroke loopback in an ultra-simple template.
|
Let's demonstrate with a clever keystroke loopback in an ultra-simple template.
|
||||||
+makeExample('user-input/ts/app/loop-back.component.ts', 'loop-back-component', 'app/loop-back.component.ts')
|
+makeExample('user-input/ts/app/loop-back.component.ts', 'loop-back-component', 'app/loop-back.component.ts')
|
||||||
:marked
|
:marked
|
||||||
We've declared a template local variable named `box` on the `<input>` element.
|
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
|
The `box` variable is a reference to the `<input>` element itself which means we can
|
||||||
grab the input element's `value` and display it
|
grab the input element's `value` and display it
|
||||||
with interpolation between `<p>` tags.
|
with interpolation between `<p>` tags.
|
||||||
|
|
||||||
The template is completely self contained. It doesn't bind to the component which does nothing.
|
The template is completely self contained. It doesn't bind to the component which does nothing.
|
||||||
|
|
||||||
Type in the input box and watch the display update with each keystroke. *Voila!*
|
Type in the input box and watch the display update with each keystroke. *Voila!*
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/user-input/keyup-loop-back-anim.gif' alt="loop back")
|
img(src='/resources/images/devguide/user-input/keyup-loop-back-anim.gif' alt="loop back")
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
**This won't work at all unless we bind to an event**.
|
**This won't work at all unless we bind to an event**.
|
||||||
|
|
||||||
Angular only updates the bindings (and therefore the screen)
|
Angular only updates the bindings (and therefore the screen)
|
||||||
if we do something in response to asynchronous events such as keystrokes.
|
if we do something in response to asynchronous events such as keystrokes.
|
||||||
|
|
||||||
That's why we bind the `keyup` event to an expression that does ... well, nothing.
|
That's why we bind the `keyup` event to an expression that does ... well, nothing.
|
||||||
We're binding to the number 0, the shortest expression we can think of.
|
We're binding to the number 0, the shortest expression we can think of.
|
||||||
That is all it takes to keep Angular happy. We said it would be clever!
|
That is all it takes to keep Angular happy. We said it would be clever!
|
||||||
@ -137,7 +137,7 @@ figure.image-display
|
|||||||
Only then do we update the component's `values` property ...
|
Only then do we update the component's `values` property ...
|
||||||
inside the event expression rather than in the component ...
|
inside the event expression rather than in the component ...
|
||||||
because we *can* ... even if it is a dubious practice.
|
because we *can* ... even if it is a dubious practice.
|
||||||
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-3' ,'app/keyup.components.ts (v3)')
|
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-3' ,'app/keyup.components.ts (v3)')
|
||||||
:marked
|
:marked
|
||||||
Here's how it works.
|
Here's how it works.
|
||||||
figure.image-display
|
figure.image-display
|
||||||
@ -153,7 +153,7 @@ figure.image-display
|
|||||||
|
|
||||||
Let's fix that by listening to the input box's blur event as well.
|
Let's fix that by listening to the input box's blur event as well.
|
||||||
|
|
||||||
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-4' ,'app/keyup.components.ts (v4)')
|
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-4' ,'app/keyup.components.ts (v4)')
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
@ -177,43 +177,43 @@ figure.image-display
|
|||||||
We've seen almost everything here before. A few things are new or bear repeating.
|
We've seen almost everything here before. A few things are new or bear repeating.
|
||||||
|
|
||||||
### *newHero* template variable
|
### *newHero* template variable
|
||||||
|
|
||||||
The *newHero* template variable refers to the `<input>` element.
|
The *newHero* template variable refers to the `<input>` element.
|
||||||
|
|
||||||
We can access `newHero` from any sibling or child of the `<input>` element.
|
We can access `newHero` from any sibling or child of the `<input>` element.
|
||||||
When the user clicks the button, we don't need a fancy css selector to
|
When the user clicks the button, we don't need a fancy CSS selector to
|
||||||
track down the textbox and extract its value.
|
track down the textbox and extract its value.
|
||||||
|
|
||||||
### Extract the input box *value*
|
### Extract the input box *value*
|
||||||
We could have passed the `newHero` into the component's `addHero()` method.
|
We could have passed the `newHero` into the component's `addHero()` method.
|
||||||
|
|
||||||
But that would require `addHero` to pick its way through the `<input>` DOM element,
|
But that would require `addHero` to pick its way through the `<input>` DOM element,
|
||||||
something we learned to dislike in our first try at a [*KeyupComponent*](#keyup1).
|
something we learned to dislike in our first try at a [*KeyupComponent*](#keyup1).
|
||||||
|
|
||||||
Instead, we grab the input box *value* and pass *that* to `addHero()`.
|
Instead, we grab the input box *value* and pass *that* to `addHero()`.
|
||||||
The component knows nothing about HTML or DOM which is the way we like it.
|
The component knows nothing about HTML or DOM which is the way we like it.
|
||||||
|
|
||||||
### Don't let template expressions be complex
|
### Don't let template expressions be complex
|
||||||
We bound `(blur)` to *two* JavaScript statements.
|
We bound `(blur)` to *two* JavaScript statements.
|
||||||
|
|
||||||
We like the first one that calls `addHero`.
|
We like the first one that calls `addHero`.
|
||||||
We do not like the second one that assigns an empty string to the input box value.
|
We do not like the second one that assigns an empty string to the input box value.
|
||||||
|
|
||||||
We did it for a good reason. We have to clear the input box after adding the new hero to the list.
|
We did it for a good reason. We have to clear the input box after adding the new hero to the list.
|
||||||
The component has no way to do that itself — because it has no access to the
|
The component has no way to do that itself — because it has no access to the
|
||||||
input box (our design choice).
|
input box (our design choice).
|
||||||
|
|
||||||
Although it *works*, we are rightly wary of JavaScript in HTML.
|
Although it *works*, we are rightly wary of JavaScript in HTML.
|
||||||
Template expressions are powerful. We're supposed to use them responsibly.
|
Template expressions are powerful. We're supposed to use them responsibly.
|
||||||
Complex JavaScript in HTML is irresponsible.
|
Complex JavaScript in HTML is irresponsible.
|
||||||
|
|
||||||
Should we reconsider our reluctance to pass the input box into the component?
|
Should we reconsider our reluctance to pass the input box into the component?
|
||||||
|
|
||||||
There should be a better third way. And there is as we'll see when we learn about `NgModel` in the [Forms](forms.html) chapter.
|
There should be a better third way. And there is as we'll see when we learn about `NgModel` in the [Forms](forms.html) chapter.
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Source code
|
## Source code
|
||||||
|
|
||||||
Here is all the code we talked about in this chapter.
|
Here is all the code we talked about in this chapter.
|
||||||
+makeTabs(`
|
+makeTabs(`
|
||||||
user-input/ts/app/click-me.component.ts,
|
user-input/ts/app/click-me.component.ts,
|
||||||
@ -237,5 +237,3 @@ figure.image-display
|
|||||||
|
|
||||||
Angular has a two-way binding called `NgModel` and we learn about it
|
Angular has a two-way binding called `NgModel` and we learn about it
|
||||||
in the `Forms` chapter.
|
in the `Forms` chapter.
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user