Skip to content

Commit 916d1f3

Browse files
crisbetotinayuangao
authored andcommitted
fix(autocomplete,datepicker,menu): closing parent dialog by pressing escape (#6226)
Prevents the autocomplete, datepicker and menu components from closing their parent dialog when the user presses escape. Fixes #6223.
1 parent a043bec commit 916d1f3

File tree

6 files changed

+28
-5
lines changed

6 files changed

+28
-5
lines changed

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
298298
_handleKeydown(event: KeyboardEvent): void {
299299
if (event.keyCode === ESCAPE && this.panelOpen) {
300300
this.closePanel();
301+
event.stopPropagation();
301302
} else if (this.activeOption && event.keyCode === ENTER && this.panelOpen) {
302303
this.activeOption._selectViaInteraction();
303304
event.preventDefault();

src/lib/autocomplete/autocomplete.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ describe('MdAutocomplete', () => {
898898
it('should close the panel when pressing escape', async(() => {
899899
const trigger = fixture.componentInstance.trigger;
900900
const escapeEvent = createKeyboardEvent('keydown', ESCAPE);
901+
const stopPropagationSpy = spyOn(escapeEvent, 'stopPropagation').and.callThrough();
901902

902903
input.focus();
903904

@@ -909,6 +910,7 @@ describe('MdAutocomplete', () => {
909910

910911
expect(document.activeElement).toBe(input, 'Expected input to continue to be focused.');
911912
expect(trigger.panelOpen).toBe(false, 'Expected panel to be closed.');
913+
expect(stopPropagationSpy).toHaveBeenCalled();
912914
});
913915
}));
914916

src/lib/datepicker/datepicker.spec.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ import {MdDatepickerInput} from './datepicker-input';
99
import {MdInputModule} from '../input/index';
1010
import {MdNativeDateModule} from '../core/datetime/index';
1111
import {ESCAPE, OverlayContainer} from '../core';
12-
import {dispatchFakeEvent, dispatchMouseEvent, dispatchKeyboardEvent} from '@angular/cdk/testing';
1312
import {DEC, JAN} from '../core/testing/month-constants';
13+
import {
14+
dispatchFakeEvent,
15+
dispatchMouseEvent,
16+
createKeyboardEvent,
17+
dispatchEvent,
18+
} from '@angular/cdk/testing';
1419

1520
describe('MdDatepicker', () => {
1621
afterEach(inject([OverlayContainer], (container: OverlayContainer) => {
@@ -134,13 +139,17 @@ describe('MdDatepicker', () => {
134139
let content = document.querySelector('.cdk-overlay-pane md-datepicker-content')!;
135140
expect(content).toBeTruthy('Expected datepicker to be open.');
136141

137-
let keyboadEvent = dispatchKeyboardEvent(content, 'keydown', ESCAPE);
142+
const keyboardEvent = createKeyboardEvent('keydown', ESCAPE);
143+
const stopPropagationSpy = spyOn(keyboardEvent, 'stopPropagation').and.callThrough();
144+
145+
dispatchEvent(content, keyboardEvent);
138146
fixture.detectChanges();
139147

140148
content = document.querySelector('.cdk-overlay-pane md-datepicker-content')!;
141149

142150
expect(content).toBeFalsy('Expected datepicker to be closed.');
143-
expect(keyboadEvent.defaultPrevented)
151+
expect(stopPropagationSpy).toHaveBeenCalled();
152+
expect(keyboardEvent.defaultPrevented)
144153
.toBe(true, 'Expected default ESCAPE action to be prevented.');
145154
});
146155

src/lib/datepicker/datepicker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ export class MdDatepickerContent<D> implements AfterContentInit {
106106
if (event.keyCode === ESCAPE) {
107107
this.datepicker.close();
108108
event.preventDefault();
109+
event.stopPropagation();
109110
}
110111
}
111112
}

src/lib/menu/menu-directive.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
168168
switch (event.keyCode) {
169169
case ESCAPE:
170170
this.close.emit('keydown');
171+
event.stopPropagation();
171172
break;
172173
case LEFT_ARROW:
173174
if (this.parentMenu && this.direction === 'ltr') {

src/lib/menu/menu.spec.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ import {
2929
} from './index';
3030
import {MENU_PANEL_TOP_PADDING} from './menu-trigger';
3131
import {extendObject} from '../core/util/object-extend';
32-
import {dispatchKeyboardEvent, dispatchMouseEvent} from '@angular/cdk/testing';
32+
import {
33+
dispatchKeyboardEvent,
34+
dispatchMouseEvent,
35+
dispatchEvent,
36+
createKeyboardEvent,
37+
} from '@angular/cdk/testing';
3338

3439

3540
describe('MdMenu', () => {
@@ -103,11 +108,15 @@ describe('MdMenu', () => {
103108
fixture.componentInstance.trigger.openMenu();
104109

105110
const panel = overlayContainerElement.querySelector('.mat-menu-panel')!;
106-
dispatchKeyboardEvent(panel, 'keydown', ESCAPE);
111+
const event = createKeyboardEvent('keydown', ESCAPE);
112+
const stopPropagationSpy = spyOn(event, 'stopPropagation').and.callThrough();
113+
114+
dispatchEvent(panel, event);
107115
fixture.detectChanges();
108116
tick(500);
109117

110118
expect(overlayContainerElement.textContent).toBe('');
119+
expect(stopPropagationSpy).toHaveBeenCalled();
111120
}));
112121

113122
it('should open a custom menu', () => {

0 commit comments

Comments
 (0)