¿Cómo puedo escuchar el evento de pulsación de tecla en toda la página?

109

Estoy buscando una forma de vincular una función a toda mi página (cuando un usuario presiona una tecla, quiero que active una función en mi componente.ts)

Fue fácil en AngularJS con a ng-keypresspero no funciona con (keypress)="handleInput($event)".

Lo probé con un contenedor div en toda la página, pero no parece funcionar. solo funciona cuando el foco está en él.

<div (keypress)="handleInput($event)" tabindex="1">
L.querter
fuente
¿Usted ha intentado window:keypress?
KarolDepka

Respuestas:

203

Me gustaría utilizar @HostListener decorador dentro de su componente:

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

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

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

También hay otras opciones como:

propiedad del anfitrión dentro del @Componentdecorador

Angular recomienda usar @HostListenerdecorador sobre la propiedad del host https://angular.io/guide/styleguide#style-06-03

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

renderer.escuchar

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();
  }
}
yurzui
fuente
2
Trabajando bien. importar {HostListener} de '@ angular / core' tiene que agregar. e incluso llamar a cualquier parte del componente. Incluso el constructor lateral también funciona bien
gnganpath
23
Gracias por esto, pero solo un aviso para los futuros lectores: si necesita las teclas de flecha, use la tecla hacia abajo en lugar de presionar la tecla.
Troels Larsen
14
Si necesita la escclave, use keyupevent. Gracias a @TroelsLarsen
Aron Lorincz
@yurzui, ¿cómo puedo usar este evento para component.not particular, en la página entera
kamalav
1
@yurzui ¿Cómo puedo detectar un function-key(F1, F2, F3, ...)?
Arpit Kumar
18

La respuesta de yurzui no funcionó para mí, podría ser una versión RC diferente, o podría ser un error de mi parte. De cualquier manera, así es como lo hice con mi componente en Angular2 RC4 (que ahora está bastante desactualizado).

@Component({
    ...
    host: {
        '(document:keydown)': 'handleKeyboardEvents($event)'
    }
})
export class MyComponent {
    ...
    handleKeyboardEvents(event: KeyboardEvent) {
        this.key = event.which || event.keyCode;
    }
}
Adán
fuente
3
Eso es lo mismo, solo sintaxis alternativa y usó en keydownlugar dekeypress
Günter Zöchbauer
Como dije, probablemente un error de mi parte, pero eso fue lo que hizo falta para que me funcionara. :)
Adam
¿Cuál sería el beneficio de esto frente al uso de document.addEventListener? ¿Es solo una cuestión de abstraer el DOM?
Ixonal
@Ixonal # 2 en este artículo describe mejor de lo que puedo: angularjs.blogspot.ca/2016/04/… Básicamente, no es la forma 'Angular', porque está acoplada con el navegador y no se puede probar. Quizás no sea gran cosa en este momento, pero es un buen modelo a seguir.
Adam
1
Los últimos documentos recomiendan usar @HostListener: angular.io/docs/ts/latest/guide/…
saschwarz
11

Solo para agregar a esto en 2019 w Angular 8,

en lugar de presionar teclas, tuve que usar keydown

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

a

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

Stacklitz de trabajo

tshoemake
fuente
Informe de Angular 9: tanto la pulsación de tecla como la pulsación de tecla registrarían teclas "asdf" normales, pero solo la pulsación de tecla obtendría F4 y otras teclas de función. La pulsación de tecla podría obtener algunas combinaciones de teclas como CTRL-Z, keydown las interpreta por separado (una tecla CTRL, luego milisegundos más tarde, una tecla Z).
Anders8
4

Si desea realizar cualquier evento en cualquier botón específico del teclado, en ese caso, puede usar @HostListener. Para ello, debe importar HostListener en el archivo ts de su componente.

importar {HostListener} desde '@ angular / core';
luego use la siguiente función en cualquier lugar del archivo ts de su componente.

@HostListener('document:keyup', ['$event'])
  handleDeleteKeyboardEvent(event: KeyboardEvent) {
    if(event.key === 'Delete')
    {
      // remove something...
    }
  }
Prabhat Maurya
fuente
0

Creo que esto hace el mejor trabajo

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

por ejemplo en app.component

constructor(private eventManager: EventManager) {
    const removeGlobalEventListener = this.eventManager.addGlobalEventListener(
      'document',
      'keypress',
      (ev) => {
        console.log('ev', ev);
      }
    );
  }
Whisher
fuente