Skip to content

Commit

Permalink
fix(overlay): always dispatch keyboard events to top overlay in Overl…
Browse files Browse the repository at this point in the history
…ayKeyboardDispatcher

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 angular#10799.
  • Loading branch information
crisbeto committed Apr 11, 2018
1 parent 23cedc1 commit d7b71fa
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 36 deletions.
22 changes: 0 additions & 22 deletions src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,28 +86,6 @@ describe('OverlayKeyboardDispatcher', () => {
button.parentNode!.removeChild(button);
});

it('should dispatch targeted keyboard events to the overlay containing that target', () => {
const overlayOne = overlay.create();
const overlayTwo = overlay.create();
const overlayOneSpy = jasmine.createSpy('overlayOne keyboard event spy');
const overlayTwoSpy = jasmine.createSpy('overlayOne keyboard event spy');

overlayOne.keydownEvents().subscribe(overlayOneSpy);
overlayTwo.keydownEvents().subscribe(overlayTwoSpy);

// Attach overlays
keyboardDispatcher.add(overlayOne);
keyboardDispatcher.add(overlayTwo);

const overlayOnePane = overlayOne.overlayElement;

dispatchKeyboardEvent(document.body, 'keydown', ESCAPE, overlayOnePane);

// Targeted overlay should receive event
expect(overlayOneSpy).toHaveBeenCalled();
expect(overlayTwoSpy).not.toHaveBeenCalled();
});

it('should complete the keydown stream on dispose', () => {
const overlayRef = overlay.create();
const completeSpy = jasmine.createSpy('keydown complete spy');
Expand Down
16 changes: 2 additions & 14 deletions src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,6 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
}
}

/** Select the appropriate overlay from a keydown event. */
private _selectOverlayFromEvent(event: KeyboardEvent): OverlayRef {
// Check if any overlays contain the event
const targetedOverlay = this._attachedOverlays.find(overlay => {
return overlay.overlayElement === event.target ||
overlay.overlayElement.contains(event.target as HTMLElement);
});

// Use the overlay if it exists, otherwise choose the most recently attached one
return targetedOverlay || this._attachedOverlays[this._attachedOverlays.length - 1];
}

/** Detaches the global keyboard event listener. */
private _detach() {
if (this._isAttached) {
Expand All @@ -85,8 +73,8 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
/** Keyboard event listener that will be attached to the body. */
private _keydownListener = (event: KeyboardEvent) => {
if (this._attachedOverlays.length) {
// Dispatch keydown event to the correct overlay.
this._selectOverlayFromEvent(event)._keydownEvents.next(event);
// Dispatch the keydown event to the top overlay.
this._attachedOverlays[this._attachedOverlays.length - 1]._keydownEvents.next(event);
}
}
}
Expand Down

0 comments on commit d7b71fa

Please sign in to comment.