Reputation: 380
I'm adding keyboard shortcuts in my application, and one of those is Shift + F which triggers the focus method on a specific input e.g. my search field.
The input-element can exist anywhere in the component tree so my approach is to use a Service with an EventEmitter and a Directive which listen to it.
SomeComponent
@Component({ .. })
export class SomeComponent {
@HostListener('document:keypress', ['$event'])
onKeyDown(event: KeyboardEvent) {
if (event.shiftKey) {
let key = event.key;
if (key === 'F') {
this.focusService.focus('mySearchBox');
}
}
}
constructor(private focusService: FocusService) { }
}
Somewhere in the html i apply a focus directive.
<input focus="mySearchBox">
FocusDirective
@Directive({
selector: '[focus]'
})
export class FocusDirective implements AfterViewInit {
@Input() focus: string;
constructor(
private elementRef: ElementRef,
private focusService: FocusService) { }
ngAfterViewInit() {
this.focusService.focusSource.subscribe(res => {
this.setFocus(res);
});
}
setFocus(item: string) {
// I use strings to match the call with the input
if (this.focus === item) { // 'mySearchBox' === 'mySearchBox
this.elementRef.nativeElement.focus();
// Do something to avoid the keypress event
}
}
}
FocusService
@Injectable()
export class FocusService {
focusSource = new EventEmitter<string>();
focus(string) {
this.focusSource.emit(string);
}
}
The problem
If I just call focusService.focus('mySearchBox) it works, however since i'm listening for keyboard events, the focus is set and the F is added to the input value.
Can I somehow avoid this behavior (preferably in the directive) so that the input ignores the keypress?
I've tried resetting the value of the input, but the F gets added after the method is finished so there is no use.
Upvotes: 3
Views: 3839
Reputation: 50633
Try using preventDefault()
:
let key = event.key;
if (key === 'F') {
event.preventDefault();
this.focusService.focus('mySearchBox');
}
The event.preventDefault() method stops the default action of an element from happening.
Read more about preventDefault()
here.
Edit:
You might need to listen to keydown
event instead of keypress
.
@HostListener('keydown', ['$event'])
Upvotes: 2