Wie kann ich auf der gesamten Seite auf ein Tastendruckereignis warten?

109

Ich suche nach einer Möglichkeit, eine Funktion an meine gesamte Seite zu binden (wenn ein Benutzer eine Taste drückt, soll sie eine Funktion in meiner component.ts auslösen).

Es war einfach in AngularJS mit einem, ng-keypressaber es funktioniert nicht mit (keypress)="handleInput($event)".

Ich habe es mit einem Div-Wrapper auf der ganzen Seite versucht, aber es scheint nicht zu funktionieren. es funktioniert nur, wenn der Fokus darauf liegt.

<div (keypress)="handleInput($event)" tabindex="1">
L.querter
quelle
Hast du es versucht window:keypress?
KarolDepka

Antworten:

203

Ich würde @ HostListener Decorator in Ihrer Komponente verwenden:

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

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

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

Es gibt auch andere Optionen wie:

Host-Eigenschaft innerhalb @ComponentDekorateur

Angular empfiehlt die Verwendung von @HostListenerDecorator über die Host-Eigenschaft 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();
  }
}
Yurzui
quelle
2
Gut funktionieren. {HostListener} aus '@ angle / core' importieren muss hinzufügen. und rufen Sie sogar überall in der Komponente. Auch
Außenbauer
23
Vielen Dank dafür, aber nur ein Hinweis für zukünftige Leser: Wenn Sie die Pfeiltasten benötigen, verwenden Sie Keydown anstelle von Tastendruck.
Troels Larsen
14
Wenn Sie den escSchlüssel benötigen , verwenden Sie keyupevent. Vielen Dank an @TroelsLarsen
Aron Lorincz
@yurzui, wie kann ich dieses Ereignis für bestimmte Komponente verwenden.
Nicht
1
@yurzui Wie kann ich ein function-key(F1, F2, F3, ...) erkennen?
Arpit Kumar
18

Die Antwort von yurzui hat bei mir nicht funktioniert, es könnte sich um eine andere RC-Version handeln oder um einen Fehler von meiner Seite. So oder so habe ich es mit meiner Komponente in Angular2 RC4 gemacht (die jetzt ziemlich veraltet ist).

@Component({
    ...
    host: {
        '(document:keydown)': 'handleKeyboardEvents($event)'
    }
})
export class MyComponent {
    ...
    handleKeyboardEvents(event: KeyboardEvent) {
        this.key = event.which || event.keyCode;
    }
}
Adam
quelle
3
Das ist die gleiche, nur alternative Syntax und Sie haben keydownstattdessenkeypress
Günter Zöchbauer
Wie ich schon sagte, wahrscheinlich ein Fehler von meiner Seite, aber genau das war nötig, um es für mich zum Laufen zu bringen. :)
Adam
Was wäre der Vorteil davon gegenüber der Verwendung von document.addEventListener? Geht es nur darum, das DOM zu abstrahieren?
Ixonal
@Ixonal # 2 in diesem Artikel beschreibt besser als ich kann: angularjs.blogspot.ca/2016/04/… Grundsätzlich ist es nicht der 'Angular'-Weg, da er mit dem Browser gekoppelt und nicht testbar ist. Vielleicht im Moment keine große Sache, aber es ist ein gutes Modell, dem man folgen kann.
Adam
1
Die neuesten Dokumente empfehlen die Verwendung von @HostListener: angle.io/docs/ts/latest/guide/…
saschwarz
11

Nur um dies im Jahr 2019 w Angular 8 hinzuzufügen,

Anstelle des Tastendrucks musste ich Keydown verwenden

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

zu

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

Working Stacklitz

tshoemake
quelle
Angular 9-Bericht: Sowohl Tastendruck als auch Tastendruck würden normale "asdf" -Tasten registrieren, aber nur Tastendruck würde F4 und andere Funktionstasten erhalten. Durch Drücken der Taste können einige Tastenkombinationen wie STRG-Z angezeigt werden. Bei Tastendruck werden diese separat interpretiert (eine STRG-Taste, dann Millisekunden später eine Z-Taste).
Anders8
4

Wenn Sie ein Ereignis auf einem bestimmten Tastendruck ausführen möchten, können Sie in diesem Fall @HostListener verwenden. Dazu müssen Sie HostListener in Ihre ts-Datei importieren.

{HostListener} aus '@ angle / core' importieren;
Verwenden Sie dann die folgende Funktion an einer beliebigen Stelle in der ts-Datei Ihrer Komponente.

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

Ich denke, das macht den besten Job

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

zum Beispiel in app.component

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