Как я могу прослушивать событие нажатия клавиши на всей странице?

109

Я ищу способ привязать функцию ко всей моей странице (когда пользователь нажимает клавишу, я хочу, чтобы она запускала функцию в моем component.ts)

В AngularJS это было легко с помощью, ng-keypressно он не работает с (keypress)="handleInput($event)".

Я пробовал использовать обертку div на всей странице, но похоже, что это не работает. он работает только тогда, когда на нем сосредоточено внимание.

<div (keypress)="handleInput($event)" tabindex="1">
L.querter
источник
Вы пробовали window:keypress?
KarolDepka 01

Ответы:

203

Я бы использовал декоратор @HostListener в вашем компоненте:

import { HostListener } from '@angular/core';

@Component({
  ...
})
export class AppComponent {

  @HostListener('document:keypress', ['$event'])
  handleKeyboardEvent(event: KeyboardEvent) { 
    this.key = event.key;
  }
}

Есть и другие варианты:

свойство хоста в @Componentдекораторе

Angular рекомендует использовать @HostListenerдекоратор поверх свойства хоста https://angular.io/guide/styleguide#style-06-03

@Component({
  ...
  host: {
    '(document:keypress)': 'handleKeyboardEvent($event)'
  }
})
export class AppComponent {
  handleKeyboardEvent(event: KeyboardEvent) {
    console.log(event);
  }
}

renderer.listen

import { Component, Renderer2 } from '@angular/core';

@Component({
  ...
})
export class AppComponent {
  globalListenFunc: Function;

  constructor(private renderer: Renderer2) {}

  ngOnInit() {
    this.globalListenFunc = this.renderer.listen('document', 'keypress', e => {
      console.log(e);
    });
  }

  ngOnDestroy() {
    // remove listener
    this.globalListenFunc();
  }
}

Observable.fromEvent

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { Subscription } from 'rxjs/Subscription';

@Component({
  ...
})
export class AppComponent {
  subscription: Subscription;

  ngOnInit() {
    this.subscription = Observable.fromEvent(document, 'keypress').subscribe(e => {
      console.log(e);
    })
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}
Юрзуй
источник
2
Работаю нормально. импорт {HostListener} из '@ angular / core' нужно добавить. и звоните даже в любом месте компонента. Даже внешний конструктор тоже работает нормально
gnganapath
23
Спасибо за это, но хочу предупредить будущих читателей: если вам нужны клавиши со стрелками, используйте клавишу вниз вместо нажатия клавиши.
Troels Larsen
14
Если вам нужен escключ, используйте keyupevent. Спасибо @TroelsLarsen
Арон Лоринц
@yurzui, как я могу использовать это событие для конкретного компонента. не на всей странице
kamalav
1
@yurzui Как я могу определить function-key(F1, F2, F3, ...)?
Арпит Кумар
18

Ответ yurzui не сработал для меня, это может быть другая версия RC или это может быть ошибка с моей стороны. В любом случае, вот как я сделал это с моим компонентом в Angular2 RC4 (который сейчас сильно устарел).

@Component({
    ...
    host: {
        '(document:keydown)': 'handleKeyboardEvents($event)'
    }
})
export class MyComponent {
    ...
    handleKeyboardEvents(event: KeyboardEvent) {
        this.key = event.which || event.keyCode;
    }
}
Адам
источник
3
Это то же самое, только альтернативный синтаксис, и вы использовали его keydownвместоkeypress
Günter Zöchbauer
Как я уже сказал, возможно, это ошибка с моей стороны, но это то, что мне потребовалось, чтобы заставить его работать для меня. :)
Адам
В чем преимущество этого по сравнению с использованием document.addEventListener? Это просто проблема абстрагирования от DOM?
Ixonal 03
@Ixonal # 2 в этой статье описывает лучше, чем я могу: angularjs.blogspot.ca/2016/04/… По сути, это не «Angular» способ, потому что он связан с браузером и не тестируется. Возможно, сейчас это не имеет большого значения, но это хорошая модель для подражания.
Адам
1
В последних документах рекомендуется использовать @HostListener: angular.io/docs/ts/latest/guide/…
saschwarz
12

Просто чтобы добавить к этому в 2019 году Angular 8,

вместо нажатия клавиши мне пришлось использовать нажатие клавиши

@HostListener('document:keypress', ['$event'])

к

@HostListener('document:keydown', ['$event'])

Рабочий Stacklitz

tshoemake
источник
Отчет Angular 9: и нажатие клавиши, и нажатие клавиши будут регистрировать обычные клавиши «asdf», но только нажатие клавиши получит F4 и другие функциональные клавиши. Нажатие клавиши может получить некоторые комбинации клавиш, такие как CTRL-Z, нажатие клавиши интерпретирует их отдельно (клавиша CTRL, затем через миллисекунды, клавиша Z).
Anders8,
4

Если вы хотите выполнить какое-либо событие при нажатии любой конкретной кнопки клавиатуры, в этом случае вы можете использовать @HostListener. Для этого вам необходимо импортировать HostListener в файл ts вашего компонента.

импортировать {HostListener} из '@ angular / core';
затем используйте функцию ниже в любом месте вашего ts файла компонента.

@HostListener('document:keyup', ['$event'])
  handleDeleteKeyboardEvent(event: KeyboardEvent) {
    if(event.key === 'Delete')
    {
      // remove something...
    }
  }
Прабхат Маурья
источник
0

Я думаю, это лучше всего работает

https://angular.io/api/platform-browser/EventManager

например, в app.component

constructor(private eventManager: EventManager) {
    const removeGlobalEventListener = this.eventManager.addGlobalEventListener(
      'document',
      'keypress',
      (ev) => {
        console.log('ev', ev);
      }
    );
  }
Whisher
источник