Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit f4a51fc

Browse files
Jade Troubleshooting - reverting to master version
1 parent 463e4cc commit f4a51fc

File tree

1 file changed

+118
-116
lines changed

1 file changed

+118
-116
lines changed
+118-116
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,65 @@
11
include ../_util-fns
22

33
:marked
4-
User actions such as clicking a link, pushing a button, and entering
5-
text raise DOM events.
6-
This page explains how to bind to those events using the Angular
4+
When the user clicks a link, pushes a button, or enters text
5+
we want to know about it. These user actions all raise DOM events.
6+
In this chapter we learn to bind to those events using the Angular
77
event binding syntax.
88

9-
.l-sub-section
10-
:marked
11-
Run the <live-example></live-example>.
9+
Run the <live-example></live-example>.
1210

1311
:marked
1412
## Binding to user input events
1513

16-
You can use [Angular event bindings](./template-syntax.html#event-binding)
17-
to respond to any [DOM event](https://developer.mozilla.org/en-US/docs/Web/Events).
18-
Many DOM events are triggered by user input. Binding to these events provides a way to
19-
get input from the user.
20-
21-
To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted
22-
[template statement](./template-syntax.html#template-statements) to it.
14+
We can use [Angular event bindings](./template-syntax.html#event-binding)
15+
to respond to [any DOM event](https://developer.mozilla.org/en-US/docs/Web/Events).
2316

24-
The following example shows an event binding that implements a click handler:
17+
The syntax is simple. We surround the DOM event name in parentheses and assign a quoted template statement to it.
18+
As an example, here's an event binding that implements a click handler:
2519
+makeExample('user-input/ts/app/click-me.component.ts', 'click-me-button')(format=".", language="html")
2620

2721
<a id="click"></a>
2822
:marked
29-
The `(click)` to the left of the equals sign identifies the button's click event as the **target of the binding**.
30-
The text in quotes to the right of the equals sign
31-
is the **template statement**, which responds
32-
to the click event by calling the component's `onClickMe` method.
23+
The `(click)` to the left of the equal sign identifies the button's click event as the **target of the binding**.
24+
The text within quotes on the right is the **template statement** in which we
25+
respond to the click event by calling the component's `onClickMe` method. A [template statement](./template-syntax.html#template-statements) is a subset
26+
of JavaScript with restrictions and a few added tricks.
3327

34-
When writing a binding, be aware of a template statement's **execution context**.
35-
The identifiers in a template statement belong to a specific context object,
36-
usually the Angular component controlling the template.
37-
The example above shows a single line of HTML, but that HTML belongs to a larger component:
28+
When writing a binding we must be aware of a template statement's **execution context**.
29+
The identifiers appearing within a statement belong to a specific context object.
30+
That object is usually the Angular component that controls the template ... which it definitely is
31+
in this case because that snippet of HTML belongs to the following component:
3832

3933
+makeExample('user-input/ts/app/click-me.component.ts', 'click-me-component', 'app/click-me.component.ts')(format=".")
4034
:marked
41-
When the user clicks the button, Angular calls the `onClickMe` method from `ClickMeComponent`.
35+
When the user clicks the button, Angular calls the component's `onClickMe` method.
4236

4337
.l-main-section
4438
:marked
4539
## Get user input from the $event object
46-
This section shows how to bind to the `keyup` event of an onscreen text box
47-
to get user input, then echo the input back to the screen.
40+
We can bind to all kinds of events. Let's bind to the keyup event of an input box and replay
41+
what the user types back onto the screen.
4842

49-
The following code listens to the `keyup` event and gets the user's input.
43+
This time we'll (1) listen to an event and (2) grab the user's input.
5044
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-template', 'app/keyup.components.ts (template v.1)')(format=".")
5145
:marked
52-
When a user presses and releases a key, the `keyup` event occurs, and Angular provides a corresponding
53-
DOM event object in the `$event` variable.
54-
The event object contains the user input data; that is, whatever key the user pressed.
55-
The code passes `$event` as a parameter to the component's `onKey()` method.
46+
Angular makes an event object available in the **`$event`** variable,
47+
which we pass to the component's `onKey()` method.
48+
The user data we want is in that variable somewhere.
5649
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class-no-type', 'app/keyup.components.ts (class v.1)')(format=".")
5750
:marked
58-
The expression `event.target.value` in the example code
59-
represents the character the user typed.
60-
The properties of an event object vary depending on the type of DOM event. For example,
61-
a mouse event includes different information than a textbox editing event. However, like all
62-
[standard DOM event objects](https://developer.mozilla.org/en-US/docs/Web/API/Event),
63-
the event object returned by `keyup` contains a property called
64-
`target`. The `target` property gives an
51+
The shape of the `$event` object is determined by whatever raises the event.
52+
The `keyup` event comes from the DOM, so `$event` must be a [standard DOM event object](https://developer.mozilla.org/en-US/docs/Web/API/Event).
53+
The `$event.target` gives us an
6554
[`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement), which
66-
has a `value` property. For a keypress event, the `value` property contains the letter, number, or other character
67-
that the user pressed on the keyboard.
55+
has a `value` property that contains our user input data.
6856

69-
The `onKey()` component method gets the user's keystroke
70-
from the event object, then adds it to the list of user data
71-
in the component's `values` property.
72-
Then the [interpolation](./template-syntax.html#interpolation)
73-
displays the accumulated user input from the `values` property, followed by a pipe character (|).
57+
The `onKey()` component method is where we extract the user's input
58+
from the event object, adding that input to the list of user data that we're accumulating in the component's `values` property.
59+
We then use [interpolation](./template-syntax.html#interpolation)
60+
to display the accumulating `values` property back on screen.
7461

75-
Suppose the user enters the letters "abc", and then backspaces to remove them one by one.
62+
Enter the letters "abc", and then backspace to remove them.
7663
Here's what the UI displays:
7764
code-example().
7865
a | ab | abc | ab | a | |
@@ -82,77 +69,78 @@ figure.image-display
8269
<a id="keyup1"></a>
8370
.l-sub-section
8471
:marked
85-
This example casts the `$event` as an `any` type.
86-
In this way, the code is simplified, but strong typing is lost.
87-
88-
In the following example, the method is rewritten to cast to HTML DOM objects:
72+
We cast the `$event` as an `any` type, which means we've abandoned strong typing
73+
to simplify our code. We generally prefer the strong typing that TypeScript affords.
74+
We can rewrite the method, casting to HTML DOM objects like this.
8975
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class', 'app/keyup.components.ts (class v.1 - strongly typed )')(format=".")
9076
:marked
9177
<br>Strong typing reveals a serious problem with passing a DOM event into the method:
92-
too much awareness of template details, and too little separation of concerns.
78+
too much awareness of template details, too little separation of concerns.
9379

94-
The next section shows how to use template reference variables to address this problem.
80+
We'll address this problem in our next try at processing user keystrokes.
81+
:marked
9582

9683
.l-main-section
9784
:marked
9885
## Get user input from a template reference variable
99-
As mentioned in the previous section, it is not ideal to pass an event variable into a method
100-
to get user input. But there's another way to get the user data: use Angular
101-
[**template reference variables**](./template-syntax.html#ref-vars).
102-
These variables grant direct access to an element.
103-
To declare a template reference variable, precede an identifier with a hash (or pound) character (#).
104-
105-
The following example uses a template reference variable
106-
to implement a keystroke loopback in a simple template.
86+
There's another way to get the user data without the `$event` variable.
87+
88+
Angular has a syntax feature called [**template reference variables**](./template-syntax.html#ref-vars).
89+
These variables grant us direct access to an element.
90+
We declare a template reference variable by preceding an identifier with a hash/pound character (#).
91+
92+
Here's an example of using a template reference variable
93+
to implement a clever keystroke loopback in an ultra-simple template.
10794
+makeExample('user-input/ts/app/loop-back.component.ts', 'loop-back-component', 'app/loop-back.component.ts')(format=".")
10895
:marked
109-
The template reference variable named `box`, declared on the `<input>` element,
110-
refers to the `<input>` element itself.
111-
The code uses the `box` variable to get the input element's `value` and display it
96+
We've declared a template reference variable named `box` on the `<input>` element.
97+
The `box` variable is a reference to the `<input>` element itself, which means we can
98+
grab the input element's `value` and display it
11299
with interpolation between `<p>` tags.
113100

114101
The template is completely self contained. It doesn't bind to the component,
115102
and the component does nothing.
116103

117-
Type something in the input box, and watch the display update with each keystroke.
104+
Type in the input box, and watch the display update with each keystroke. *Voila!*
118105

119106
figure.image-display
120107
img(src='/resources/images/devguide/user-input/keyup-loop-back-anim.gif' alt="loop back")
121108
.l-sub-section
122109
:marked
123-
**This won't work unless you bind to an event**.
124-
125-
Angular updates the bindings (and therefore the screen)
126-
only if the app does something in response to asynchronous events, such as keystrokes.
127-
This example code binds the `keyup` event
128-
to the number 0, the shortest template statement possible. The statement
129-
does nothing, but it satisfies Angular's requirement so that Angular will
130-
update the screen.
131-
:marked
132-
It's easier to get to the textbox with the template reference
133-
variable than to go through the `$event` object. Here's a rewrite of the previous
134-
`keyup` example that uses a template reference variable to get the user's input.
110+
**This won't work at all unless we bind to an event**.
111+
112+
Angular only updates the bindings (and therefore the screen)
113+
if we do something in response to asynchronous events such as keystrokes.
114+
115+
That's why we bind the `keyup` event to a statement that does ... well, nothing.
116+
We're binding to the number 0, the shortest statement we can think of.
117+
That is all it takes to keep Angular happy. We said it would be clever!
118+
:marked
119+
That template reference variable is intriguing. It's clearly easier to get to the textbox with that
120+
variable than to go through the `$event` object. Maybe we can rewrite our previous
121+
keyup example so that it uses the variable to get the user's input. Let's give it a try.
135122
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-2' ,'app/keyup.components.ts (v2)')(format=".")
136123
:marked
137-
A nice aspect of this approach is that the component code gets clean data values from the view.
124+
That sure seems easier.
125+
An especially nice aspect of this approach is that our component code gets clean data values from the view.
138126
It no longer requires knowledge of the `$event` and its structure.
139127

140128
<a id="key-event"></a>
141129
.l-main-section
142130
:marked
143-
## Key event filtering (with `keyup.enter`)
144-
Sometimes only the Enter key matters, because it signals that the user has finished typing.
145-
But the `(keyup)` event handler hears *every keystroke.*
146-
One way to reduce the noise would be to examine every `$event.keyCode` and take action when the key is Enter.
147-
But there's an easier way: bind to Angular's `keyup.enter` pseudo-event. With this pseudo-event,
148-
Angular calls the event handler only when the user presses Enter.
131+
## Key event filtering (with `key.enter`)
132+
Perhaps we don't care about every keystroke.
133+
Maybe we're only interested in the input box value when the user presses Enter, and we'd like to ignore all other keys.
134+
When we bind to the `(keyup)` event, our event handling statement hears *every keystroke*.
135+
We could filter the keys first, examining every `$event.keyCode`, and update the `values` property only if the key is Enter.
149136

150-
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-3' ,'app/keyup.components.ts (v3)')(format=".")
137+
Angular can filter the key events for us. Angular has a special syntax for keyboard events.
138+
We can listen for just the Enter key by binding to Angular's `keyup.enter` pseudo-event.
151139

152-
.l-sub-section
153-
:marked
154-
In this example, the data binding expression handles the event. It's a better practice
155-
to minimize JavaScript in HTML. Move this code to the component.
140+
Only then do we update the component's `values` property. (In this example,
141+
the update happens inside the event binding statement. A better practice
142+
would be to put the update code in the component.)
143+
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-3' ,'app/keyup.components.ts (v3)')(format=".")
156144
:marked
157145
Here's how it works.
158146
figure.image-display
@@ -162,62 +150,76 @@ figure.image-display
162150
:marked
163151
## On blur
164152

165-
In the previous example, the current state of the input box
166-
is lost if the user mouses away and clicks elsewhere on the page
167-
without first pressing Enter.
168-
The component's `values` property is updated only when the user presses Enter.
153+
Our previous example won't transfer the current state of the input box if the user mouses away and clicks
154+
elsewhere on the page. We update the component's `values` property only when the user presses Enter
155+
while the focus is inside the input box.
169156

170-
To fix this issue, listen to both the Enter key and the blur event.
157+
Let's fix that by listening to the input box's blur event as well.
171158

172159
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-4' ,'app/keyup.components.ts (v4)')(format=".")
173160

174161
.l-main-section
175162
:marked
176163
## Put it all together
177-
The previous page showed how to [display data](./displaying-data.html).
178-
This page demonstrated event binding techniques.
164+
We learned how to [display data](./displaying-data.html) in the previous chapter.
165+
We've acquired a small arsenal of event binding techniques in this chapter.
179166

180-
Now, put it all together in a micro-app
181-
that can display a list of heroes and add new heroes to the list.
182-
The user can add a hero by typing the hero's name in the input box and
183-
clicking **Add**.
167+
Let's put it all together in a micro-app
168+
that can display a list of heroes and add new heroes to that list.
169+
The user can add a hero by first typing in the input box and then
170+
pressing Enter, clicking the Add button, or clicking elsewhere on the page.
184171

185172
figure.image-display
186173
img(src='/resources/images/devguide/user-input/little-tour-anim.gif' alt="Little Tour of Heroes")
187174
:marked
188175
Below is the "Little Tour of Heroes" component.
176+
We'll call out the highlights after we bask briefly in its minimalist glory.
189177

190178
+makeExample('user-input/ts/app/little-tour.component.ts', 'little-tour', 'app/little-tour.component.ts')(format=".")
191179
:marked
180+
We've seen almost everything here before. A few things are new or bear repeating.
181+
192182
### Use template variables to refer to elements
193183

194184
The `newHero` template variable refers to the `<input>` element.
195-
You can use `newHero` from any sibling or child of the `<input>` element.
185+
We can use `newHero` from any sibling or child of the `<input>` element.
196186

197187
Getting the element from a template variable makes the button click handler
198-
simpler. Without the variable, the code would have to include a CSS selector
188+
simpler. Without the variable, we'd have to use a fancy CSS selector
199189
to find the input element.
200190

201191
### Pass values, not elements
202192

203-
Instead of passing the `newHero` into the component's `addHero` method,
204-
get the input box value and pass *that* to `addHero`.
193+
We could have passed the `newHero` into the component's `addHero` method.
194+
195+
But that would require `addHero` to pick its way through the `<input>` DOM element,
196+
something we learned to dislike in our first try at a [keyup component](#keyup1).
197+
198+
Instead, we grab the input box *value* and pass *that* to `addHero`.
199+
The component knows nothing about HTML or the DOM, which is the way we like it.
205200

206201
### Keep template statements simple
207-
The `(blur)` event is bound to two JavaScript statements.
208-
The first statement calls `addHero`. The second statement, `newHero.value=''`,
209-
clears the input box after a new hero is added to the list.
202+
We bound `(blur)` to *two* JavaScript statements.
203+
204+
We like the first one, which calls `addHero`.
205+
We do not like the second one, which assigns an empty string to the input box value.
206+
207+
The second statement exists for a good reason. We have to clear the input box after adding the new hero to the list.
208+
The component has no way to do that itself because it has no access to the
209+
input box (our design choice).
210+
211+
Although the example *works*, we are rightly wary of JavaScript in HTML.
212+
Template statements are powerful. We're supposed to use them responsibly.
213+
Complex JavaScript in HTML is irresponsible.
210214

211-
This works well enough for a demonstration, but
212-
it is better not to combine JavaScript and HTML.
213-
This example can be improved by using `NgModel`, as described in
214-
[Forms](./forms.html).
215+
Should we reconsider our reluctance to pass the input box into the component?
215216

217+
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.
216218
.l-main-section
217219
:marked
218220
## Source code
219221

220-
Following is all the code discussed in this page.
222+
Here is all the code we talked about in this chapter.
221223
+makeTabs(`
222224
user-input/ts/app/click-me.component.ts,
223225
user-input/ts/app/keyup.components.ts,
@@ -233,10 +235,10 @@ figure.image-display
233235
:marked
234236
## Summary
235237

236-
You have mastered the basic primitives for responding to user input and gestures.
238+
We've mastered the basic primitives for responding to user input and gestures.
239+
As powerful as these primitives are, they are a bit clumsy for handling
240+
large amounts of user input. We're operating down at the low level of events when
241+
we should be writing two-way bindings between data entry fields and model properties.
237242

238-
These techniques are useful for small-scale demonstrations, but they quickly become verbose and clumsy when handling
239-
large amounts of user input.
240-
Two-way data binding is a more elegant and compact way to move values between data entry fields and model properties.
241-
The next page, `Forms`, explains how to write
242-
two-way bindings with `NgModel`.
243+
Angular has a two-way binding called `NgModel`, which we'll learn about
244+
in the `Forms` chapter.

0 commit comments

Comments
 (0)