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

Commit f4f30e1

Browse files
committed
Adding key-binding cookbook.
This cookbook demonstrates how to use the key-combination support provided by Angular's `KeyEventsPlugin`. This allows developers to tap into element-level events like `keydown.Escape` and `keydown.Meta.Enter`.
1 parent 2bc166c commit f4f30e1

File tree

11 files changed

+281
-0
lines changed

11 files changed

+281
-0
lines changed

public/docs/_examples/cb-key-bindings/.gitignore

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// gulp run-e2e-tests --filter=cb-key-bindings --fast
2+
describe('Key combination bindings', function () {
3+
4+
beforeAll(function () {
5+
browser.get('');
6+
});
7+
8+
it('should pick up key combinations', function () {
9+
10+
var input = element( by.css( 'input' ) );
11+
12+
input.click();
13+
14+
input.sendKeys( protractor.Key.ENTER );
15+
expect( element.all( by.css( 'li' ) ).last().getText() ).toContain( 'Enter' );
16+
17+
input.sendKeys( protractor.Key.SHIFT, protractor.Key.ENTER );
18+
expect( element.all( by.css( 'li' ) ).last().getText() ).toContain( 'Shift+Enter' );
19+
20+
input.sendKeys( protractor.Key.META, protractor.Key.ENTER );
21+
expect( element.all( by.css( 'li' ) ).last().getText() ).toContain( 'Meta+Enter' );
22+
23+
input.sendKeys( ' ' );
24+
expect( element.all( by.css( 'li' ) ).last().getText() ).toContain( 'Space' );
25+
26+
input.sendKeys( 'a' );
27+
expect( element.all( by.css( 'li' ) ).last().getText() ).toContain( 'a' );
28+
29+
input.sendKeys( protractor.Key.SHIFT, 'a' );
30+
expect( element.all( by.css( 'li' ) ).last().getText() ).toContain( 'A' );
31+
32+
input.sendKeys( protractor.Key.ESCAPE );
33+
expect( element.all( by.css( 'li' ) ).last().getText() ).toContain( 'Escape' );
34+
35+
});
36+
37+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// #docregion
2+
// Import the native Angular services.
3+
import { Component } from '@angular/core';
4+
5+
// #docregion component
6+
@Component({
7+
selector: 'cb-app',
8+
template:
9+
`
10+
<input
11+
(keydown.Enter)='handleKey( "Enter" )'
12+
(keydown.Meta.Enter)='handleKey( "Meta+Enter" )'
13+
(keydown.Shift.Enter)='handleKey( "Shift+Enter" )'
14+
(keydown.Control.Enter)='handleKey( "Control+Enter" )'
15+
(keydown.Alt.Enter)='handleKey( "Alt+Enter" )'
16+
(keydown.Alt.Meta.Enter)='handleKey( "Alt+Meta+Enter" )'
17+
(keydown.Shift.Meta.Enter)='handleKey( "Shift+Meta+Alt+Enter" )'
18+
(keydown.Alt.Shift.Meta.Enter)='handleKey( "Alt+Shift+Meta+Alt+Enter" )'
19+
(keydown.Control.Alt.Shift.Meta.Enter)='handleKey( "Control+Alt+Shift+Meta+Alt+Enter" )'
20+
(keydown.Shift)='handleKey( "Shift" )'
21+
22+
(keydown.a)='handleKey( "a" )'
23+
(keydown.Shift.a)='handleKey( "A" )'
24+
(keydown.Shift.?)='handleKey( "?" )'
25+
(keydown.Tab)='handleKey( "Tab :: CANCELED", $event )'
26+
(keydown.Space)='handleKey( "Space" )'
27+
(keydown.Dot)='handleKey( "Dot" )'
28+
29+
(keydown.ArrowLeft)='handleKey( "ArrowLeft" )'
30+
(keydown.ArrowUp)='handleKey( "ArrowUp" )'
31+
(keydown.ArrowRight)='handleKey( "ArrowRight" )'
32+
(keydown.ArrowDown)='handleKey( "ArrowDown" )'
33+
(keydown.ArrowDown)='handleKey( "ArrowDown" )'
34+
(keydown.End)='handleKey( "End" )'
35+
(keydown.Home)='handleKey( "Home" )'
36+
(keydown.PageDown)='handleKey( "PageDown" )'
37+
(keydown.PageUp)='handleKey( "PageUp" )'
38+
39+
(keydown.Meta.s)='handleKey( "Meta+S (Save) :: CANCELED", $event )'
40+
(keydown.Meta.o)='handleKey( "Meta+O (Open) :: CANCELED", $event )'
41+
(keydown.Meta.p)='handleKey( "Meta+P (Print) :: CANCELED", $event )'
42+
(keydown.Meta.f)='handleKey( "Meta+F (Find) :: CANCELED", $event )'
43+
44+
(keydown.Escape)='handleKey( "Escape" )'
45+
autofocus>
46+
47+
<ul>
48+
<li *ngFor='let item of logItems'>
49+
Key event: {{ item }}
50+
</li>
51+
</ul>
52+
`
53+
})
54+
export class AppComponent {
55+
56+
public logItems: string[];
57+
58+
constructor() {
59+
this.logItems = [];
60+
}
61+
62+
public handleKey( description: string, event?: KeyboardEvent ) : void {
63+
// If the user pressed the ESC key, clear the log.
64+
if ( description === 'Escape' ) {
65+
this.logItems = [];
66+
}
67+
68+
this.logItems.push( description );
69+
70+
// If the event object is present, prevent the default behavior of the key press.
71+
event && event.preventDefault();
72+
}
73+
74+
}
75+
// #enddocregion component
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// #docregion
2+
// Import the native Angular services.
3+
import { bootstrap } from '@angular/platform-browser-dynamic';
4+
5+
// Import the application services and components.
6+
import { AppComponent } from './app.component';
7+
8+
bootstrap( AppComponent )
9+
.then(
10+
() => {
11+
console.info( 'Angular finished bootstrapping your application!' );
12+
},
13+
( error ) => {
14+
console.warn( 'Angular was not able to bootstrap your application.' );
15+
console.error( error );
16+
}
17+
)
18+
;

public/docs/_examples/cb-key-bindings/ts/example-config.json

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<base href="/">
7+
8+
<title>
9+
Binding To Key Combination Events
10+
</title>
11+
12+
<link rel="stylesheet" type="text/css" href="./styles.css" />
13+
<link rel="stylesheet" type="text/css" href="./sample.css" />
14+
15+
<!-- Polyfill(s) for older browsers -->
16+
<script src="node_modules/core-js/client/shim.min.js"></script>
17+
18+
<script src="node_modules/zone.js/dist/zone.js"></script>
19+
<script src="node_modules/reflect-metadata/Reflect.js"></script>
20+
<script src="node_modules/systemjs/dist/system.src.js"></script>
21+
22+
<script src="systemjs.config.js"></script>
23+
<script>
24+
System.import('app')
25+
.then(function() { console.info( "System.js loaded your application module." )})
26+
.catch(function(err){ console.error(err); });
27+
</script>
28+
</head>
29+
<body>
30+
31+
<h1>
32+
Binding To Key Combination Events
33+
</h1>
34+
35+
<cb-app>Loading app...</cb-app>
36+
37+
</body>
38+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"description": "Set The Document Title In Angular 2",
3+
"files": [
4+
"!**/*.d.ts",
5+
"!**/*.js",
6+
"!**/*.[1].*"
7+
],
8+
"tags": [ "cookbook" ]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
input {
2+
font-size: 20px ;
3+
width: 400px ;
4+
}

public/docs/ts/latest/cookbook/_data.json

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
"intro": "Render dynamic forms with NgFormModel"
3232
},
3333

34+
"key-bindings": {
35+
"title": "Key Bindings",
36+
"intro": "Binding to Key Combinations"
37+
},
38+
3439
"set-document-title": {
3540
"title": "Set the Document Title",
3641
"intro": "Setting the document or window title using the Title service."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
include ../_util-fns
2+
3+
a( id='top' )
4+
5+
:marked
6+
With Angular's powerful event-binding syntax, we can bind to any native DOM
7+
(Document Object Model) event by wrapping the **event type** in parentheses.
8+
For example, if we wanted to bind to the `focus` or `click` event, we would
9+
add an element binding for `(focus)` or `(click)`, respectively. The same can
10+
be done for `(keydown)`, `(keyup)`, and `(keypress)` events. However, with
11+
key events, we generally want to do more than _just_ bind to the event
12+
&mdash; we want to respond to specific key combinations. Luckily, Angular's
13+
event-binding system can help us accomplish this as well.
14+
15+
:marked
16+
When defining a `keydown` or `keyup` event-binding, we can provide additional
17+
settings that determine which keyboard events will cause our event handler to
18+
be invoked. In the event-binding syntax, these settings are provided as a
19+
dot-delimited suffix to the core event type.
20+
21+
:marked
22+
So, for example, if we wanted to respond specifically to the `Enter` key in a
23+
`keydown` event, we would add the following element binding:
24+
`(keydown.Enter)`. And, if we wanted to respond to the increasingly-popular
25+
`Command+Enter` key combination, we would add the following element binding:
26+
`(keydown.Meta.Enter)`.
27+
28+
:marked
29+
Any alpha-numeric character can be used in the event-binding as long as it
30+
doesn't break the HTML parser (Caution: `>` will break the parser). Special
31+
characters like the period and the space are made available via `Dot` and
32+
`Space`, respectively. In addition, [many control characters](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#Key_values)
33+
like `ArrowLeft` and `ArrowRight` can be used as well.
34+
35+
.l-sub-section
36+
:marked
37+
Commonly-used control characters include:
38+
39+
* `Enter`
40+
* `Escape`
41+
* `ArrowLeft`, `ArrowUp`, `ArrowRight`, `ArrowDown`
42+
* `Tab`
43+
44+
:marked
45+
The following modifier modifiers can be used (either on their own or in
46+
combination with other modifiers and characters):
47+
48+
:marked
49+
* `Alt`
50+
* `Control`
51+
* `Meta` (`Command` key on the Mac, `Start` key on Windows)
52+
* `Shift`
53+
54+
:marked
55+
None of the event-binding settings are case-sensitive. `Tab` is the same as
56+
`tab` and `A` is the same as `a`. However, the event settings have to match
57+
on all event conditions. This means that our event-bindings have to account
58+
for modifier keys if modifier keys are required in order to render the target
59+
character. For example:
60+
61+
:marked
62+
* `keydown.a` codes for `a`.
63+
* `keydown.Shift.a` codes for `A` _(if the Shift key was depressed)_.
64+
* `keydown.Shift.?` codes for the question mark.
65+
66+
:marked
67+
In the following code, we're attaching multiple key combination events to a
68+
single `input` and then logging the key values to a list:
69+
70+
:marked
71+
**See the [live example](/resources/live-examples/cb-key-bindings/ts/plnkr.html)**.
72+
73+
+makeExample( 'cb-key-bindings/ts/app/app.component.ts', 'component', 'app/app.component.ts' )(format='.')
74+
75+
:marked
76+
When we run this demo and try some of the key combination bindings, we get
77+
the following output:
78+
79+
figure.image-display
80+
img(src='/resources/images/cookbooks/key-bindings/key-bindings.gif' alt='Key Bindings')
81+
82+
:marked
83+
When we use these key bindings, Angular doesn't alter the behavior of the
84+
keys in any way. As such, if we want to override the default behavior
85+
(such as preventing the `Tab` key from removing focus from an input), we
86+
have to call the `.preventDefault()` method on the associated event object.
87+
88+
:marked
89+
At the time of this writing, these special key combination settings are only
90+
supported at the element level and only for the `keydown` and `keyup` events.
91+
Meaning, these cannot be used with the global `window:` or `document:`
92+
targets; and, they cannot be used with the `keypress` event.
93+
94+
:marked
95+
[Back to top](#top)
Loading

0 commit comments

Comments
 (0)