3

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.

1 Answer 1

2

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'])
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.