0

I'm trying to implement a MatTable with keyboard interaction, in order to select the rows inside the table.

For the keyboard interaction, I've used FocusKeyManager from Cdk's- a11y module. Also, the keydown event is attached to the host (mat-table).

this.keyManager = new FocusKeyManager<MatRowFocusableDirective>(
  this.rows
).withHomeAndEnd();


@HostListener("keydown", ["$event"])
public onKeydownHandler(event: KeyboardEvent): void {
 this.keyManager.onKeydown(event);
}

At this point, everything works fine.

But I wanted to extend the keyboard interaction, similar to the Gmail web app:

  • on any keypress (up/down arrow) inside the document, I want to start the navigation inside the table:

    @HostListener("document:keydown", ["$event"])
    public onKeydownHandler(event: KeyboardEvent): void {
      this.keyManager.onKeydown(event);
    }
    

This works, but, in the app, I also use other Angular Material components that are build upon CDK Overlays, like Dialogs, Selects, Bottomsheets, etc.

The issue is that when one of these components is opened, the keyboard interaction within the table is still available.

How can I disable the keyboard interaction within the table when any of the CDK Overlay components is opened?

Demo: https://stackblitz.com/edit/angular-tspvfu-onnsdk

andreivictor
  • 7,628
  • 3
  • 48
  • 75
  • Your stackblitz code works good, with the exeception that if you use the Up/Down arrow keys it does not update the activeItemIndex. – Mark Jun 25 '21 at 18:22

1 Answers1

1

You could try the following:

  1. Create a service with a shouldFocusOnKeyboard property (name it how you want).
  2. Use cdkMonitorSubtreeFocus or cdkMonitorElementFocus to detect when elements outside of your table received focus.
  3. On each element you applied the monitoring directive to, use the cdkFocusChange event to change the value of shouldFocusOnKeyboard.
  4. Use the new service to determine whether to pass the document:keydown event to the keyManager or not.

Focus monitoring with CDK

Pro Tip:
A better design would probably be to create the shouldFocusOnKeyboard as a BehaviorSubject<boolean> and pipe it in your event handler.

Shy Agam
  • 1,285
  • 1
  • 13
  • 37