Skip to content

Commit d7b71fa

Browse files
committed
fix(overlay): always dispatch keyboard events to top overlay in OverlayKeyboardDispatcher
Currently when dispatching events through the `OverlayKeyboardDispatcher` we try to match one of the overlays to the element that triggered the event. This is problematic, because some components will open an overlay, but will keep focus on the trigger element (e.g. `mat-autocomplete` and `mat-select`). These changes switch the logic so the keyboard events are always dispatched to the top-level overlay. Fixes #10799.
1 parent 23cedc1 commit d7b71fa

File tree

2 files changed

+2
-36
lines changed

2 files changed

+2
-36
lines changed

src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.spec.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -86,28 +86,6 @@ describe('OverlayKeyboardDispatcher', () => {
8686
button.parentNode!.removeChild(button);
8787
});
8888

89-
it('should dispatch targeted keyboard events to the overlay containing that target', () => {
90-
const overlayOne = overlay.create();
91-
const overlayTwo = overlay.create();
92-
const overlayOneSpy = jasmine.createSpy('overlayOne keyboard event spy');
93-
const overlayTwoSpy = jasmine.createSpy('overlayOne keyboard event spy');
94-
95-
overlayOne.keydownEvents().subscribe(overlayOneSpy);
96-
overlayTwo.keydownEvents().subscribe(overlayTwoSpy);
97-
98-
// Attach overlays
99-
keyboardDispatcher.add(overlayOne);
100-
keyboardDispatcher.add(overlayTwo);
101-
102-
const overlayOnePane = overlayOne.overlayElement;
103-
104-
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE, overlayOnePane);
105-
106-
// Targeted overlay should receive event
107-
expect(overlayOneSpy).toHaveBeenCalled();
108-
expect(overlayTwoSpy).not.toHaveBeenCalled();
109-
});
110-
11189
it('should complete the keydown stream on dispose', () => {
11290
const overlayRef = overlay.create();
11391
const completeSpy = jasmine.createSpy('keydown complete spy');

src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,6 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
6262
}
6363
}
6464

65-
/** Select the appropriate overlay from a keydown event. */
66-
private _selectOverlayFromEvent(event: KeyboardEvent): OverlayRef {
67-
// Check if any overlays contain the event
68-
const targetedOverlay = this._attachedOverlays.find(overlay => {
69-
return overlay.overlayElement === event.target ||
70-
overlay.overlayElement.contains(event.target as HTMLElement);
71-
});
72-
73-
// Use the overlay if it exists, otherwise choose the most recently attached one
74-
return targetedOverlay || this._attachedOverlays[this._attachedOverlays.length - 1];
75-
}
76-
7765
/** Detaches the global keyboard event listener. */
7866
private _detach() {
7967
if (this._isAttached) {
@@ -85,8 +73,8 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
8573
/** Keyboard event listener that will be attached to the body. */
8674
private _keydownListener = (event: KeyboardEvent) => {
8775
if (this._attachedOverlays.length) {
88-
// Dispatch keydown event to the correct overlay.
89-
this._selectOverlayFromEvent(event)._keydownEvents.next(event);
76+
// Dispatch the keydown event to the top overlay.
77+
this._attachedOverlays[this._attachedOverlays.length - 1]._keydownEvents.next(event);
9078
}
9179
}
9280
}

0 commit comments

Comments
 (0)