zhinee
zhinee

Reputation: 135

Angular: When using mat-select , Is there a way to not select the focused item when I press SPACE button?

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

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.

Upvotes: 5

Views: 9713

Answers (4)

Mas Agung Sachli
Mas Agung Sachli

Reputation: 1

@Eliseo answer is correct. Unfortunately, in Angular 16, _handleOpenKeydown & _handleClosedKeydown method are marked as private.

My way out to override the function is calling the parent's method. And I can't use event.keyCode because it is deprecated. So I need to use event.key.

ngOnInit(): void {
    this.select._handleKeydown = (event:KeyboardEvent)=>{
        if (event.key === ' ' ) return
        MatSelect.prototype._handleKeydown.call(this.select, event)
    }
}

Upvotes: 0

akelec
akelec

Reputation: 4003

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>

Upvotes: 10

Eliseo
Eliseo

Reputation: 57999

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

Upvotes: 9

georg.dev
georg.dev

Reputation: 1263

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.

Upvotes: 1

Related Questions