@angular/cdk/keycodes package provides constants for keyboard key codes and utilities for keyboard event handling.
Installation
npm install @angular/cdk
import {ENTER, SPACE, ESCAPE} from '@angular/cdk/keycodes';
Available Key Constants
Navigation Keys
import {
UP_ARROW,
DOWN_ARROW,
LEFT_ARROW,
RIGHT_ARROW,
PAGE_UP,
PAGE_DOWN,
HOME,
END,
} from '@angular/cdk/keycodes';
Action Keys
import {
ENTER,
SPACE,
ESCAPE,
TAB,
BACKSPACE,
DELETE,
} from '@angular/cdk/keycodes';
Modifier Keys
import {
SHIFT,
CONTROL,
ALT,
META, // Command on Mac, Windows key on PC
} from '@angular/cdk/keycodes';
Letter and Number Keys
import {
A, B, C, D, E, F, G, H, I, J, K, L, M,
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
ZERO, ONE, TWO, THREE, FOUR,
FIVE, SIX, SEVEN, EIGHT, NINE,
} from '@angular/cdk/keycodes';
Usage Examples
Keyboard Navigation
import {Component, HostListener} from '@angular/core';
import {UP_ARROW, DOWN_ARROW, ENTER} from '@angular/cdk/keycodes';
@Component({
selector: 'app-navigable-list',
template: `
<div *ngFor="let item of items; let i = index"
[class.focused]="i === focusedIndex"
(click)="onSelect(i)">
{{ item }}
</div>
`,
})
export class NavigableListComponent {
items = ['Item 1', 'Item 2', 'Item 3'];
focusedIndex = 0;
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
switch (event.keyCode) {
case UP_ARROW:
event.preventDefault();
this.focusedIndex = Math.max(0, this.focusedIndex - 1);
break;
case DOWN_ARROW:
event.preventDefault();
this.focusedIndex = Math.min(this.items.length - 1, this.focusedIndex + 1);
break;
case ENTER:
event.preventDefault();
this.onSelect(this.focusedIndex);
break;
}
}
onSelect(index: number) {
console.log('Selected:', this.items[index]);
}
}
Modal Dialog Escape
import {Component, HostListener} from '@angular/core';
import {ESCAPE} from '@angular/cdk/keycodes';
@Component({
selector: 'app-modal',
template: `
<div class="modal-overlay">
<div class="modal-content">
<h2>{{ title }}</h2>
<button (click)="close()">Close</button>
</div>
</div>
`,
})
export class ModalComponent {
@Input() title: string;
@Output() closed = new EventEmitter<void>();
@HostListener('document:keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
if (event.keyCode === ESCAPE) {
this.close();
}
}
close() {
this.closed.emit();
}
}
Keyboard Shortcuts
import {Component, HostListener} from '@angular/core';
import {S, CONTROL, META} from '@angular/cdk/keycodes';
@Component({
selector: 'app-editor',
template: `
<textarea [(ngModel)]="content"></textarea>
<p *ngIf="saved">Saved!</p>
`,
})
export class EditorComponent {
content = '';
saved = false;
@HostListener('document:keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
// Ctrl+S or Cmd+S to save
if ((event.ctrlKey || event.metaKey) && event.keyCode === S) {
event.preventDefault();
this.save();
}
}
save() {
console.log('Saving:', this.content);
this.saved = true;
setTimeout(() => this.saved = false, 2000);
}
}
Custom Dropdown
import {Component, HostListener} from '@angular/core';
import {ENTER, SPACE, ESCAPE, UP_ARROW, DOWN_ARROW} from '@angular/cdk/keycodes';
@Component({
selector: 'app-dropdown',
template: `
<button (click)="toggleOpen()" #trigger>
{{ selected || 'Select...' }}
</button>
<div *ngIf="isOpen" class="dropdown">
<div *ngFor="let option of options; let i = index"
[class.highlighted]="i === highlightedIndex"
(click)="selectOption(option)"
(mouseenter)="highlightedIndex = i">
{{ option }}
</div>
</div>
`,
})
export class DropdownComponent {
options = ['Option 1', 'Option 2', 'Option 3'];
selected: string;
isOpen = false;
highlightedIndex = 0;
toggleOpen() {
this.isOpen = !this.isOpen;
if (this.isOpen) {
this.highlightedIndex = 0;
}
}
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
if (!this.isOpen) {
if (event.keyCode === ENTER || event.keyCode === SPACE) {
event.preventDefault();
this.toggleOpen();
}
return;
}
switch (event.keyCode) {
case UP_ARROW:
event.preventDefault();
this.highlightedIndex = Math.max(0, this.highlightedIndex - 1);
break;
case DOWN_ARROW:
event.preventDefault();
this.highlightedIndex = Math.min(this.options.length - 1, this.highlightedIndex + 1);
break;
case ENTER:
case SPACE:
event.preventDefault();
this.selectOption(this.options[this.highlightedIndex]);
break;
case ESCAPE:
event.preventDefault();
this.isOpen = false;
break;
}
}
selectOption(option: string) {
this.selected = option;
this.isOpen = false;
}
}
Utility Functions
hasModifierKey
Check if a modifier key is pressed:import {Component, HostListener} from '@angular/core';
import {hasModifierKey} from '@angular/cdk/keycodes';
@Component({
selector: 'app-modifier-demo',
template: `<div>Click with modifiers</div>`,
})
export class ModifierDemo {
@HostListener('click', ['$event'])
onClick(event: MouseEvent) {
if (hasModifierKey(event)) {
console.log('Clicked with modifier key');
}
if (hasModifierKey(event, 'shiftKey')) {
console.log('Shift key is pressed');
}
if (hasModifierKey(event, 'ctrlKey', 'altKey')) {
console.log('Ctrl or Alt is pressed');
}
}
}
Complete Key Constants List
// Navigation
UP_ARROW = 38
DOWN_ARROW = 40
LEFT_ARROW = 37
RIGHT_ARROW = 39
PAGE_UP = 33
PAGE_DOWN = 34
HOME = 36
END = 35
// Actions
ENTER = 13
SPACE = 32
ESCAPE = 27
TAB = 9
BACKSPACE = 8
DELETE = 46
// Modifiers
SHIFT = 16
CONTROL = 17
ALT = 18
META = 91 // Windows key or Command key
// Letters (A-Z = 65-90)
A = 65
B = 66
// ... and so on
// Numbers (0-9 = 48-57)
ZERO = 48
ONE = 49
// ... and so on
Best Practices
- Prevent default - Call
event.preventDefault()when handling navigation keys - Accessibility - Support keyboard navigation for all interactive elements
- Cross-platform - Use
hasModifierKeyfor cross-platform modifier detection - Focus management - Ensure proper focus when handling keyboard events
- Standard shortcuts - Follow platform conventions (Ctrl on Windows, Cmd on Mac)
Common Patterns
List Navigation
case UP_ARROW:
event.preventDefault();
this.focusPrevious();
break;
case DOWN_ARROW:
event.preventDefault();
this.focusNext();
break;
Close on Escape
if (event.keyCode === ESCAPE) {
this.close();
}
Submit on Enter
if (event.keyCode === ENTER && !event.shiftKey) {
event.preventDefault();
this.submit();
}