How can I listen for keypress event on the whole page?

144,644

Solution 1

I would use @HostListener decorator within your component:

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

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

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

There are also other options like:

host property within @Component decorator

Angular recommends using @HostListener decorator over host property 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();
  }
}

Solution 2

yurzui's answer didn't work for me, it might be a different RC version, or it might be a mistake on my part. Either way, here's how I did it with my component in Angular2 RC4 (which is now quite outdated).

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

Solution 3

Just to add to this in 2019 w Angular 8,

instead of keypress I had to use keydown

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

to

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

Working Stacklitz

Solution 4

If you want to perform any event on any specific keyboard button press, in that case, you can use @HostListener. For this, you have to import HostListener in your component ts file.

import { HostListener } from '@angular/core';
then use below function anywhere in your component ts file.

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

Solution 5

Be aware "document:keypress" is deprecated. We should use document:keydown instead.

Link: https://developer.mozilla.org/fr/docs/Web/API/Document/keypress_event

Share:
144,644
L.querter
Author by

L.querter

Working mostly in Dotnet Core. Experience in Golang, Nodejs and Python scripting.

Updated on July 29, 2020

Comments

  • L.querter
    L.querter almost 4 years

    I'm looking for a way to bind a function to my whole page (when a user presses a key, I want it to trigger a function in my component.ts)

    It was easy in AngularJS with a ng-keypress but it does not work with (keypress)="handleInput($event)".

    I tried it with a div wrapper on the whole page but it doesn't seem to work. it only works when the focus is on it.

    <div (keypress)="handleInput($event)" tabindex="1">
    
    • KarolDepka
      KarolDepka over 5 years
      Have you tried window:keypress?
  • Günter Zöchbauer
    Günter Zöchbauer almost 8 years
    That's the same, just alternative syntax and you used keydown instead of keypress
  • Adam
    Adam almost 8 years
    Like I said, probably a mistake on my part, but that's what it took to get it to work for me. :)
  • Ixonal
    Ixonal almost 8 years
    What would be the benefit of this vs using document.addEventListener? Is it just an issue of abstracting away the DOM?
  • Adam
    Adam almost 8 years
    @Ixonal #2 on this articles describes better than I can: angularjs.blogspot.ca/2016/04/… Basically, it's not the 'Angular' way, because it's coupled with the browser, and it's not testable. Maybe not a big deal right now, but it's a good model to follow.
  • saschwarz
    saschwarz over 7 years
    The latest docs recommend using @HostListener: angular.io/docs/ts/latest/guide/…
  • gnganapath
    gnganapath about 7 years
    Werking fine. import {HostListener } from '@angular/core' have to add. and call even anywhere in component. Even out side contructor also working fine
  • Troels Larsen
    Troels Larsen about 7 years
    Thanks for this, but just a heads up for future readers: if you need the arrow keys, use keydown instead of keypress.
  • Admin
    Admin about 7 years
    doesnt work!property 'key' does not exists in the current context.
  • Adam
    Adam about 7 years
    You can't just copy-paste code and expect it to work without modifications @ritesh. You need to either define key as a class variable, or change the assignment to assign to a local variable.
  • Aron Lorincz
    Aron Lorincz almost 7 years
    If you need the esc key, use keyup event. Thank to @TroelsLarsen
  • kamalav
    kamalav over 6 years
    @yurzui ,how can I use this event for particular component.not on whole page
  • Arpit Kumar
    Arpit Kumar over 6 years
    @yurzui How can I detect a function-key (F1, F2, F3, ...)?
  • Rahul Singh
    Rahul Singh over 6 years
    @yurzui i wanted to ask one thing on this, this actually will trigger for the whole document what if i have multiple small components in the view and one is in focus i only want to trigger or listen to the click or mouse events for that component and all other components too have this but are not in focus ?
  • bts
    bts over 6 years
    @arpit-meena Use keydown (or keyup) instead of keypress to catch function keys. @HostListener('document:keydown', ['$event'])
  • Steinfeld
    Steinfeld over 5 years
    this won't detect 'escape'
  • Anders8
    Anders8 about 4 years
    Angular 9 report: both keypress and keydown would register normal "asdf" keys, but only keydown would get F4 and other function keys. Keypress could get some key combos like CTRL-Z, keydown interprets those separately (a CTRL key, then milliseconds later, a Z key).
  • thienedits
    thienedits about 4 years
    Can someone explain why doing this in a directive does not work? Such as in the directive having the selector choose the app-root element. This does not seem to fire any keypress events.
  • tpartee
    tpartee almost 4 years
    @yurzui You can detect Function Keys by using the keydown/keyup events and then be sure to call event.preventDefault() on the event to prevent it being handled by your browser. (For instance if you don't stop it from bubbling up, your browser will open a help screen when you press F1.)
  • Mike de Klerk
    Mike de Klerk over 2 years
    addGlobalEventListener is @deprecated — No longer being used in Ivy code. To be removed in version 14.