I have this button which when clicked opens a dropdown of checkboxes. I am able to use the 'tab' key to navigate to the button as well as hit the 'space' or 'enter' key to open the dropdown. But I am not able to navigate through the checkboxes of the dropdown by using the up and down arrow keys. This is the relevant code:
<button class = “setting-button" mat-button [matmenuTriggerfor] =“settings" <fa-icon [icon]-"settingsIcon"></fa-icon> </button>
<mat-menu #settings="matMenu" >
<div *ngFor="let id of arraycolumns">
<div *nglf=" ![‘Cashless', 'Borrower', 'options', 'isfavorite', 'Progress', 'Deal Name'].includes(id)" mat-menu-item >
<mat-checkbox class="chkbx" #singleCheckbox [checked]= 'fieldcolumnsChecked.indexof(id) >= 0' (change)="checkcolumnsChanged(id)" (click)="$event.stopPropagation();">
{{id}}
</mat-checkbox>
</div>
</div>
</mat-menu>
And in the ts file I have this:
@ViewChildren("singleCheckbox") checkboxes!: QueryList<MatCheckbox>;
How can I enable navigation through the dropdown itself? Please help! Thank you :)
I think you can make use of Angular's HostListener to listen for keyboard events and manipulate the focus.
Add a tabIndex to the mat-checkbox to make it focusable and Implement HostListener in your component to listen for keydown events.
When arrow keys are pressed, change the focus of the checkboxes accordingly.
The HTML:
<mat-menu #settings="matMenu">
<div *ngFor="let id of arraycolumns; let i = index">
<div *ngIf="![‘Cashless', 'Borrower', 'options', 'isfavorite', 'Progress', 'Deal Name'].includes(id)" mat-menu-item>
<mat-checkbox class="chkbx" #singleCheckbox [checked]='fieldcolumnsChecked.indexOf(id) >= 0' (change)="checkcolumnsChanged(id)" (click)="$event.stopPropagation();" [tabIndex]="i">
{{id}}
</mat-checkbox>
</div>
</div>
</mat-menu>
typescript:
import { HostListener, QueryList, ViewChildren } from '@angular/core';
import { MatCheckbox } from '@angular/material/checkbox';
// ... (other imports)
export class YourComponent {
@ViewChildren("singleCheckbox") checkboxes!: QueryList<MatCheckbox>;
currentFocusIndex = 0;
// ...
@HostListener('document:keydown', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
if (this.checkboxes && this.checkboxes.length) {
if (event.key === 'ArrowDown') {
event.preventDefault();
this.setFocus(true);
} else if (event.key === 'ArrowUp') {
event.preventDefault();
this.setFocus(false);
}
}
}
setFocus(goDown: boolean) {
if (goDown && this.currentFocusIndex < this.checkboxes.length - 1) {
this.currentFocusIndex++;
} else if (!goDown && this.currentFocusIndex > 0) {
this.currentFocusIndex--;
}
const checkboxArray = this.checkboxes.toArray();
checkboxArray[this.currentFocusIndex].focus();
}
// ... (rest of your code)
}