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.