Home > Software design >  Angulars HostListener interfers with focused HTML object
Angulars HostListener interfers with focused HTML object

Time:11-15

I have two components, NavBarComponent and FooComponent.

I attached a HostListener to FooComponent and I have an input field in NavBarComponent.

FooComponent

@HostListener('document:keydown', ['$event'])
onKeydownHandler(event: KeyboardEvent): void { 
    switch (event.code) {
        case 'ArrowLeft': {
            /* do something in this component */
            $event.stopPropagation();
            break;
        }
    }
});

Despite the fact that document.activeElement returns the <input ...> field from the navigation component, the FooComponent consumes the <-- arrow left event.

Of course, that happens because I call stopPropagation, but I assumed the listener wouldn't get the event at all since the input field has the focus. Am I missing something here?

CodePudding user response:

It does get the event since 'document:keydown' (or 'window:keydown') is a global hook.

What you might want to do is to skip your code when the FooComponent or any of its children inside DOM are not the target. Something like this:

@HostListener('document:keydown', ['$event'])
onKeydownHandler(event: KeyboardEvent): void {
  switch (event.code) {
    case 'ArrowLeft': {
      if (this.elemRef.nativeElement.contains(event.target)) {
        /* do something in this component */
        event.stopPropagation();
        break;
      }
    }
  }
};

And then add this dependency inside the constructor:

constructor(
  private elemRef: ElementRef,

This should allow you to use the left arrow key inside the input box of the NavBarComponent.


By the way, for me in Chrome, the event is not actually prevented until I also add return false; immediately after event.stopPropagation();. As far as I know, it's always a good practice to return also a falsy value when you want to cancel an event.

  • Related