Skip to content

Commit d3cdb34

Browse files
authored
fix(material/menu): unable to move focus from inside opened event (#20968)
We move focus inside the menu after we've dispatched the `menuOpened` event which means that we'll override any focus that the consumer may have set inside the handler. These changes fix the issue by changing the order. Fixes #20965.
1 parent 060ab9e commit d3cdb34

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

src/material-experimental/mdc-menu/menu.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,21 @@ describe('MDC-based MatMenu', () => {
10441044
.toBe(false);
10451045
});
10461046

1047+
it('should be able to move focus inside the `open` event', fakeAsync(() => {
1048+
const fixture = createComponent(SimpleMenu, [], [FakeIcon]);
1049+
fixture.detectChanges();
1050+
1051+
fixture.componentInstance.trigger.menuOpened.subscribe(() => {
1052+
(document.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]')[3] as HTMLElement).focus();
1053+
});
1054+
fixture.componentInstance.trigger.openMenu();
1055+
fixture.detectChanges();
1056+
tick(500);
1057+
1058+
const items = document.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]');
1059+
expect(document.activeElement).toBe(items[3], 'Expected fourth item to be focused');
1060+
}));
1061+
10471062
describe('lazy rendering', () => {
10481063
it('should be able to render the menu content lazily', fakeAsync(() => {
10491064
const fixture = createComponent(SimpleLazyMenu);

src/material/menu/menu-trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,8 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
339339
this.menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;
340340
this.menu.direction = this.dir;
341341
this._setMenuElevation();
342-
this._setIsMenuOpen(true);
343342
this.menu.focusFirstItem(this._openedBy || 'program');
343+
this._setIsMenuOpen(true);
344344
}
345345

346346
/** Updates the menu elevation based on the amount of parent menus that it has. */

src/material/menu/menu.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,21 @@ describe('MatMenu', () => {
987987
.toBe(false);
988988
});
989989

990+
it('should be able to move focus inside the `open` event', fakeAsync(() => {
991+
const fixture = createComponent(SimpleMenu, [], [FakeIcon]);
992+
fixture.detectChanges();
993+
994+
fixture.componentInstance.trigger.menuOpened.subscribe(() => {
995+
(document.querySelectorAll('.mat-menu-panel [mat-menu-item]')[3] as HTMLElement).focus();
996+
});
997+
fixture.componentInstance.trigger.openMenu();
998+
fixture.detectChanges();
999+
tick(500);
1000+
1001+
const items = document.querySelectorAll('.mat-menu-panel [mat-menu-item]');
1002+
expect(document.activeElement).toBe(items[3], 'Expected fourth item to be focused');
1003+
}));
1004+
9901005
describe('lazy rendering', () => {
9911006
it('should be able to render the menu content lazily', fakeAsync(() => {
9921007
const fixture = createComponent(SimpleLazyMenu);

0 commit comments

Comments
 (0)