0

Is there a way to disable the keyboard support for printable characters, mainly letters?

I want to suppress, that an option gets selected when typing any letter.

I tried something like this, but the problem is, that i have a directive bound to a parent component, that listens for key strokes and does stuff then.

const el = this.dropdown.nativeElement.querySelector('.ui-helper-hidden-accessible');
  el.addEventListener(
    'keydown',
      (event: KeyboardEvent) => {
        event.stopPropagation();
      },
      { capture: true }
    );

Also tried event.preventDefault() and event.returnValue = false which did not help.

2 Answers2

0

To disable the selection of options in a dropdown via keyboard input, you can use the keydown event and prevent the default behavior when a printable character (letter) is pressed.

Create directive.

import { Directive, ElementRef, HostListener } from '@angular/core';

/**
 * Directive to disable keyboard support for printable characters in a dropdown.
 * Prevents selection of options when typing letters.
 */
@Directive({
  selector: '[appDisableDropdownKeyboard]',
})
export class DisableDropdownKeyboardDirective {
  constructor(private elementRef: ElementRef) {}

  /**
   * Event listener for the 'keydown' event on the host element.
   * Prevents the default behavior for printable characters (letters) and stops event propagation. Not arrow donw, up etc..
   * @param event The keyboard event.
   */
  @HostListener('keydown', ['$event'])
  onKeydown(event: KeyboardEvent) {
    event.stopPropagation();
    const printableCharacters = /[a-zA-Z]/;
    if (printableCharacters.test(event.key)) {
      event.preventDefault();
    }
  }
}

Declare directive in app.module.ts or any of your module

  declarations: [
    DisableDropdownKeyboardDirective,
  ],

And in HTML add directive.

<p-dropdown
  appDisableDropdownKeyboard
  [options]="cities"
  [(ngModel)]="selectedCity2"
  editable="true"
  optionLabel="name"
></p-dropdown>

And edited Your Stackblitz

Daniel Vágner
  • 538
  • 3
  • 19
  • @neukoellnjenny Did that help, or did you come up with a different solution? – Daniel Vágner Jun 13 '23 at 15:55
  • No it did not. event.preventDefault() is not working in this case :( – neukoellnjenny Jun 14 '23 at 07:53
  • Can you provide the complete code? From what you've provided, I don't know why this wouldn't work. I mean did you implemented in directive or some component etc... – Daniel Vágner Jun 14 '23 at 08:52
  • I tried both ways, via directive or in my component. i created a stackblitz – neukoellnjenny Jun 14 '23 at 09:50
  • https://stackblitz.com/edit/primeng-dropdown-demo-jdmed6?file=src%2Fblock-chars.directive.ts,src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.module.ts,src%2Fapp%2Fapp.component.ts – neukoellnjenny Jun 14 '23 at 09:50
  • I have modified the response and add edited StackBlitz. If the dropdown is currently focused, typing characters/letters will not trigger any action. Working example on stackblitz: https://stackblitz.com/edit/primeng-dropdown-demo-74n3sy?file=src%2Fapp%2Fdisable-dropdown-keyboard.directive.ts – Daniel Vágner Jun 14 '23 at 21:56
  • thank you very much for your effort, but that wasnt working for me. even in your stackblitz you posted, dont know why, however, found a work around for it, as posted in an answer to my question. – neukoellnjenny Jun 20 '23 at 14:00
0

This is a work-around I found for it

const element = this.dropdown.nativeElement.querySelector('.ui-helper-hidden-accessible');
    element.addEventListener(
      'keydown',
      event => {
        if(event.keyCode == 27 || event.keyCode == 13 || event.key == 'ArrowDown' || event.key == 'ArrowUp') {
          return; 
        }

        if (event.key == 'w' || event.key == 's' || event.key == 'a' || event.key == 'd') {
          this.helperService.subjectAsObservable.next(event.key);
        }

        const printableCharacters = /[a-zA-Z]/;
        if (printableCharacters.test(event.key)) {
          event.stopPropagation();
        } 
      },
      { capture: true }
    );
  }

This way I can subscribe to the observable in my parent component where i listen for the keystrokes which dont bubble now anymore and can invoke my actions i need.

you may wonder why the keys WASD, the reason is I need to navigate a form with them, left/right and up/down.