Come posso ascoltare l'evento di pressione dei tasti su tutta la pagina?


109

Sto cercando un modo per associare una funzione a tutta la mia pagina (quando un utente preme un tasto, voglio che attivi una funzione nel mio component.ts)

È stato facile in AngularJS con a ng-keypressma non funziona con (keypress)="handleInput($event)".

L'ho provato con un div wrapper su tutta la pagina ma non sembra funzionare. funziona solo quando il focus è su di esso.

<div (keypress)="handleInput($event)" tabindex="1">

Hai provato window:keypress?
KarolDepka

Risposte:


203

Vorrei utilizzare il decoratore @HostListener all'interno del tuo componente:

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

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

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

Ci sono anche altre opzioni come:

proprietà host all'interno del @Componentdecoratore

Angular consiglia di utilizzare @HostListenerDecorator sulla proprietà 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.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
Lavorando bene. import {HostListener} da "@ angular / core" da aggiungere. e chiama anche ovunque nel componente. Anche il
costruttore esterno

23
Grazie per questo, ma solo un avvertimento per i futuri lettori: se hai bisogno dei tasti freccia, usa keydown invece di keypress.
Troels Larsen

14
Se ti serve la escchiave, usa keyupevent. Grazie a @TroelsLarsen
Aron Lorincz

@yurzui, come posso utilizzare questo evento per un componente particolare. non su tutta la pagina
kamalav

1
@yurzui Come posso rilevare un function-key(F1, F2, F3, ...)?
Arpit Kumar

18

La risposta di yurzui non ha funzionato per me, potrebbe essere una versione RC diversa, o potrebbe essere un errore da parte mia. Ad ogni modo, ecco come l'ho fatto con il mio componente in Angular2 RC4 (che ora è abbastanza obsoleto).

@Component({
    ...
    host: {
        '(document:keydown)': 'handleKeyboardEvents($event)'
    }
})
export class MyComponent {
    ...
    handleKeyboardEvents(event: KeyboardEvent) {
        this.key = event.which || event.keyCode;
    }
}

3
È la stessa, solo una sintassi alternativa che hai usato al keydownposto dikeypress
Günter Zöchbauer

Come ho detto, probabilmente un errore da parte mia, ma è quello che ci è voluto per farlo funzionare per me. :)
Adam

Quale sarebbe il vantaggio di questo rispetto all'utilizzo di document.addEventListener? È solo una questione di astrarre il DOM?
Ixonal

@Ixonal # 2 in questo articolo descrive meglio di me: angularjs.blogspot.ca/2016/04/… Fondamentalmente, non è il modo "Angular", perché è accoppiato con il browser e non è testabile. Forse non è un grosso problema in questo momento, ma è un buon modello da seguire.
Adam

1
Gli ultimi documenti consigliano di utilizzare @HostListener: angular.io/docs/ts/latest/guide/…
saschwarz

11

Solo per aggiungere a questo nel 2019 w Angular 8,

invece di premere il tasto ho dovuto usare keydown

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

per

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

Stacklitz funzionante


Rapporto angolare 9: sia la pressione dei tasti che il tasto giù registrerebbero i normali tasti "asdf", ma solo il tasto giù otterrebbe F4 e altri tasti funzione. La pressione di un tasto potrebbe ottenere alcune combinazioni di tasti come CTRL-Z, keydown le interpreta separatamente (un tasto CTRL, quindi millisecondi dopo, un tasto Z).
Anders8

4

Se si desidera eseguire qualsiasi evento premendo un pulsante della tastiera specifico, in tal caso, è possibile utilizzare @HostListener. Per questo, devi importare HostListener nel file ts del componente.

importa {HostListener} da "@ angular / core";
quindi utilizzare la funzione di seguito ovunque nel file ts del componente.

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


0

Penso che questo faccia il lavoro migliore

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

ad esempio in app.component

constructor(private eventManager: EventManager) {
    const removeGlobalEventListener = this.eventManager.addGlobalEventListener(
      'document',
      'keypress',
      (ev) => {
        console.log('ev', ev);
      }
    );
  }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.