Jakob Segerslätt
Jakob Segerslätt

Reputation: 380

Focus text input with keypress in Angular 2 without adding keypress value

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

Answers (1)

Stefan Svrkota
Stefan Svrkota

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

Related Questions