Skip to content

Commit 84bb660

Browse files
committed
fix(cdk/menu): prevent default selection key actions (#26051)
Fixes that the CDK menu wasn't calling `preventDefault` on the enter key presses which caused it to immediately close, because it would allow the click handler to fire as well. Fixes #26033. (cherry picked from commit 02ab0a2)
1 parent 0cd409e commit 84bb660

File tree

4 files changed

+18
-7
lines changed

4 files changed

+18
-7
lines changed

src/cdk/menu/menu-item.spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {Component, Type, ElementRef} from '@angular/core';
22
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
3+
import {dispatchKeyboardEvent} from '@angular/cdk/testing/private';
34
import {By} from '@angular/platform-browser';
5+
import {ENTER} from '@angular/cdk/keycodes';
46
import {CdkMenuModule} from './menu-module';
57
import {CdkMenuItem} from './menu-item';
68
import {CDK_MENU} from './menu-interface';
@@ -43,7 +45,7 @@ describe('MenuItem', () => {
4345
});
4446

4547
it('should coerce the disabled property', () => {
46-
(menuItem as any).disabled = '';
48+
menuItem.disabled = '';
4749
expect(menuItem.disabled).toBeTrue();
4850
});
4951

@@ -64,6 +66,12 @@ describe('MenuItem', () => {
6466
it('should not have a menu', () => {
6567
expect(menuItem.hasMenu).toBeFalse();
6668
});
69+
70+
it('should prevent the default selection key action', () => {
71+
const event = dispatchKeyboardEvent(nativeButton, 'keydown', ENTER);
72+
fixture.detectChanges();
73+
expect(event.defaultPrevented).toBe(true);
74+
});
6775
});
6876

6977
describe('with complex inner elements', () => {

src/cdk/menu/menu-item.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ export class CdkMenuItem implements FocusableOption, FocusableElement, Toggler,
198198
case SPACE:
199199
case ENTER:
200200
if (!hasModifierKey(event)) {
201+
event.preventDefault();
201202
this.trigger({keepOpen: event.keyCode === SPACE && !this.closeOnSpacebarTrigger});
202203
}
203204
break;

src/cdk/menu/menu-trigger.spec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Component, ViewChildren, QueryList, ElementRef, ViewChild, Type} from '@
22
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
33
import {By} from '@angular/platform-browser';
44
import {dispatchKeyboardEvent} from '../../cdk/testing/private';
5-
import {TAB, SPACE} from '@angular/cdk/keycodes';
5+
import {TAB, SPACE, ENTER} from '@angular/cdk/keycodes';
66
import {CdkMenuModule} from './menu-module';
77
import {CdkMenuItem} from './menu-item';
88
import {CdkMenu} from './menu';
@@ -425,13 +425,15 @@ describe('MenuTrigger', () => {
425425
});
426426

427427
it('should toggle the menu on keyboard events', () => {
428-
dispatchKeyboardEvent(nativeTrigger, 'keydown', SPACE);
428+
const firstEvent = dispatchKeyboardEvent(nativeTrigger, 'keydown', ENTER);
429429
detectChanges();
430+
expect(firstEvent.defaultPrevented).toBe(true);
430431
expect(nativeMenus.length).toBe(2);
431432

432-
dispatchKeyboardEvent(nativeTrigger, 'keydown', SPACE);
433+
const secondEvent = dispatchKeyboardEvent(nativeTrigger, 'keydown', ENTER);
433434
detectChanges();
434435
expect(nativeMenus.length).toBe(1);
436+
expect(secondEvent.defaultPrevented).toBe(true);
435437
});
436438

437439
it('should close the open menu on background click', () => {

src/cdk/menu/menu-trigger.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,11 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnDestroy {
131131
*/
132132
_toggleOnKeydown(event: KeyboardEvent) {
133133
const isParentVertical = this._parentMenu?.orientation === 'vertical';
134-
const keyCode = event.keyCode;
135-
switch (keyCode) {
134+
switch (event.keyCode) {
136135
case SPACE:
137136
case ENTER:
138137
if (!hasModifierKey(event)) {
138+
event.preventDefault();
139139
this.toggle();
140140
this.childMenu?.focusFirstItem('keyboard');
141141
}
@@ -167,7 +167,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnDestroy {
167167
if (!isParentVertical) {
168168
event.preventDefault();
169169
this.open();
170-
keyCode === DOWN_ARROW
170+
event.keyCode === DOWN_ARROW
171171
? this.childMenu?.focusFirstItem('keyboard')
172172
: this.childMenu?.focusLastItem('keyboard');
173173
}

0 commit comments

Comments
 (0)