12

I have read How to prevent angular material mat-menu from closing? , which explains how to prevent Angular material mat-menu from closing on click.

However: I cannot seem to find a way to prevent a mat-menu from closing when I press tabulator to change focus.

Take this StackBlitz as an example: https://stackblitz.com/edit/angular-ij6jbx: it properly prevents the mat-menu from closing when the input-fields receive the focus via mouse click. On the other hand: if I press "tabulator" to change focus and the username-input-field receives the focus, the menu closes.

I would like to know how to prevent this behavior - if it's possible. I tried attaching $event.stopPropagation(); to (input), but it did not seem to do anything.

Apparently some thought has been given to this by the Angular developers according to https://github.com/angular/material2/issues/2612. Sadly there does not seem to be a proper solution at the end of the issue / feature-request nor a hint about the status.

P.s.: I know, that the current code is not beautiful nor really smart. I was going to refactor that into its own directive once it worked for both click and key-press.

Igor
  • 1,582
  • 6
  • 19
  • 49

1 Answers1

14

You can catch keydown event as follows:

<mat-menu ...>
  <form (keydown.tab)="$event.stopPropagation()">

Forked Stackblitz

Also, I would add tabindex="-1" to all clear buttons

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • Thank you for your reply! Sadly the forked StackBlitz you offered does not work as expected. I would have loved to be able to use the "tab"-key to focus onto username, then upon another press to focus on password and finally "tab" to focus the log-in button (and use "return" to log in). Possibly also use the "return"-key to log in when on username or password (but that'd be a different story). **I do not want to disregard the tab-ability** if possible. I also would like to omit turning off tabindex on anything, that's normally focusable. – Igor Jun 03 '18 at 14:59
  • 1
    Actually tab-ability is working as expected. When menu is opened angular material sets focus on the `mat-menu-item` element. Next click on tab button will move it to another element that is not part of menu. Updated example.Changed ` – yurzui Jun 03 '18 at 15:43
  • Thank you! The only thing missing is how to set the focus on the username? Meaning that once the menu is open, the first control (in this case the "username"-input-field) is focused. I tried `cdkFocusInitial`, but it does not work. Should I manually set the focus or is there a directive or something for that? Other than that: thank you very much. – Igor Jun 03 '18 at 15:51
  • Added `mat-menu-item` to input. Also see `app.component.css` https://stackblitz.com/edit/angular-hyfu7r?file=src%2Fapp%2Fapp.component.html – yurzui Jun 03 '18 at 16:09
  • 6
    Yes - that's great! **Thank you!** By the way: there is no need to have `false` at the end of the `(click)`-directive, because we do not need to `preventDefault`. Also there might be a need for shift-tab-support, which one can include using `(keydown.shift.tab)="$event.stopPropagation()"` right next to `(keydown.tab)`. – Igor Jun 03 '18 at 16:21
  • Hm one thing keeps being weird... if I use `class="mat-menu-item"` instead of the `mat-menu-item`-directive, the button's appearance is same, but it does not receive focus if "tabbed" onto using the keyboard... – Igor Jun 03 '18 at 21:47
  • You can use `ma-menu-item` attribute now since `input` element will be the first focused item anyway, but i see focus on that button in my example even when use class. Maybe that's because i added `:focus` style in app.component.css – yurzui Jun 04 '18 at 03:23
  • Actually there's still a problem: even if I add the `mat-menu-item`-directive properly, if I "**tab**" onto a focusable control outside the menu while the menu is open, the menu does not close for whatever reason. However: if I "**click**" outside, it does close as expected. Do you happen to have an idea of why this might be happening? – Igor Jun 05 '18 at 18:50
  • Works great. One may also want to add `(keydown.home)="$event.stopPropagation()"` and `(keydown.end)="$event.stopPropagation()"` – Andrew Furman Mar 12 '21 at 15:53