3

By looking at, https://v5.material.angular.io/components/select/overview
There are several keyboard interactions.

  • Keyboard interaction
  • DOWN_ARROW: Focus next option
  • UP_ARROW: Focus previous option
  • ENTER or SPACE: Select focused item

I am able to stop the whole interaction, BUT what I want is:
keep the all the keyboard interactions, except the SPACE one

Is there a way to do it?
Thank you.

Steve
  • 11,596
  • 7
  • 39
  • 53
zhinee
  • 105
  • 1
  • 10

3 Answers3

7

Take account the Georg-un's answer

But if there a great great reason you always can "re-writte" the function.

Use a template reference variable in your select

<mat-select #select="matSelect">
   ...
</mat-select>

And you can use ViewChild to get the mat select and rewrite the function

  @ViewChild('select', { static: true }) select: any;

  ngOnInit() {
    this.select._handleKeydown = (event: KeyboardEvent) => {
      if (event.keyCode==SPACE)
        return
      if (!this.select.disabled) {
        this.select.panelOpen
          ? this.select._handleOpenKeydown(event)
          : this.select._handleClosedKeydown(event);
      }
    };
  }

NOTE: SPACE is defined in

import { SPACE} from '@angular/cdk/keycodes';

Update we can use a directive also

@Directive({
  selector: '[no-space]',
})
export class NoSpaceDirective {
  @Output('spacekeydown') spacekeydown: EventEmitter<any> =
    new EventEmitter<any>();
    
constructor(@Self() private select: MatSelect) {
    this.select._handleKeydown = (event: KeyboardEvent) => {
      if (event.keyCode == SPACE) {
          const active=this.select.panelOpen?
                 this.select.options.filter(x=>x.active)[0]|| null:
                 null
        this.spacekeydown.emit(active?active.value:null);
      } else {
        if (!this.select.disabled) {
          this.select.panelOpen
            ? (this.select as any)._handleOpenKeydown(event)
            : (this.select as any)._handleClosedKeydown(event);
        }
      }
    };
  }

}

And you use as

<mat-select no-space 
     (spacekeydown)="doSomething($event)">
   ...
</mat-select>

As always, if we use as "selector" instead [no-space] mat-select

@Directive({
  selector: 'mat-select',
})
...

The directive is applied to all ours mat-select

see a stackblitz with the directive

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • It's working! Thanks a lot for the help. It's my first overriding the function from source code. Learned something new today! – zhinee Feb 14 '22 at 21:10
  • @zhinee, I update the answer to indicate how do it using a directive. I hope this can help you – Eliseo Feb 15 '22 at 07:42
  • Interesting, never thought I could use directive to achieve this functionality. Thanks a lot! – zhinee Feb 15 '22 at 14:59
4

I think this is related and it might be of interest to someone who has an input field in mat-select and needs to disable the closing of mat-select when the user presses a space in the input. You just need to prevent default behavior on click and keydown:

<mat-select>
    <mat-option
        <input 
            (click)="$event.stopPropagation()"
            (keydown)="$event.stopPropagation()">
        </input>
    </mat-option>
</mat-select>
akelec
  • 3,797
  • 3
  • 41
  • 39
  • `(keydown)="$event.stopPropagation()"` did the trick for me... I used this bit of code to focus on the input field whilst user is typing some values. – Ali Celebi Jul 11 '23 at 07:58
1

If you look at the source code, you'll find that the keys are hardcoded. Therefore, you cannot easily override them.

Besides that, you probably should not override them anyways sice this would conflict with accessibility.

georg-un
  • 1,123
  • 13
  • 24
  • really it's very easy override the function. just use ViewChild and re-define the function. But I'm agree with you about accessibility – Eliseo Feb 14 '22 at 19:54
  • Not a big fan of overriding private functions of other libraries if it is not absolutely necessary. In most cases it's just technical debt for the guy after you to take care of. But you are absolutely right that it can be overridden. In the end, its just javascript anyways. – georg-un Feb 14 '22 at 22:32
  • I general I agree with you, but you can improve some material components. e.g. you want to use F1 in the mat-select to show aditional information or you can change the icons of the mat-sort in a table... – Eliseo Feb 15 '22 at 08:10