For an Angular app, why do hotkeys not work in Chrome until the user interacts with the page

Viewed 33

Using Angular I have various HostListeners listening for keydown:

@HostListener('window:keydown', ['$event'])
keyEvent(evt: KeyboardEvent) {
  console.log(evt)
}

I can see in the console logs that this is firing. But it won't fire until I interact with the page in some way (e.g. by clicking on it first) and after that it works great.

Is this expected behaviour? If not, how do I fix it such that the hotkeys work without the user first interacting with the page?

NB: On https://duckduckgo.com the arrows keys seem to work without interacting with the page - maybe this is just something to do with TabIndex?

NB: This problem exists in Chrome. I haven't tested in other browsers.

2 Answers

It's likely because they have an element (the input) auto focused. On your application call .focus() on the body.

Came up with a crazy hacky fix for this after I noticed that the hotkeys worked after pressing the Tab key (which selected a button).

So I just added a useless button to the page and hid it off screen and set the focus on that. Now the hotkeys work on page load.

Code as follows:

TS:

@ViewChild('setFocusOnMeToMakeHotkeysWorkOnPageLoad') setFocusOnMeToMakeHotkeysWorkOnPageLoad: ElementRef<HTMLButtonElement>

ngAfterViewInit() {
  setTimeout(() => {
    this.setFocusOnMeToMakeHotkeysWorkOnPageLoad.nativeElement.focus()
  })
}

HTML:

<button #setFocusOnMeToMakeHotkeysWorkOnPageLoad id="set-focus-on-me-to-make-hotkeys-work-on-page-load"></button>

CSS:

#set-focus-on-me-to-make-hotkeys-work-on-page-load {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  top: -1000px;
}
Related