From 45d6ae4a1365664fc2e62ca83d197d1a819b42c0 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 18 Jul 2018 18:47:09 +0200 Subject: [PATCH] fix(overlay): avoid same overlay being added to the keyboard event stack multiple times (#12222) --- .../overlay-keyboard-dispatcher.spec.ts | 21 +++++++++++++++++++ .../keyboard/overlay-keyboard-dispatcher.ts | 3 +++ 2 files changed, 24 insertions(+) diff --git a/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.spec.ts b/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.spec.ts index 3f8ddd4dca8..2381d6b53f5 100644 --- a/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.spec.ts +++ b/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.spec.ts @@ -157,6 +157,27 @@ describe('OverlayKeyboardDispatcher', () => { expect(overlayOneSpy).toHaveBeenCalled(); }); + it('should not add the same overlay to the stack multiple times', () => { + const overlayOne = overlay.create(); + const overlayTwo = overlay.create(); + const overlayOneSpy = jasmine.createSpy('overlayOne keyboard event spy'); + const overlayTwoSpy = jasmine.createSpy('overlayTwo keyboard event spy'); + + overlayOne.keydownEvents().subscribe(overlayOneSpy); + overlayTwo.keydownEvents().subscribe(overlayTwoSpy); + + keyboardDispatcher.add(overlayOne); + keyboardDispatcher.add(overlayTwo); + keyboardDispatcher.add(overlayOne); + + dispatchKeyboardEvent(document.body, 'keydown', ESCAPE); + + expect(keyboardDispatcher._attachedOverlays).toEqual([overlayTwo, overlayOne]); + + expect(overlayTwoSpy).not.toHaveBeenCalled(); + expect(overlayOneSpy).toHaveBeenCalled(); + }); + }); diff --git a/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.ts b/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.ts index a0886b218a8..13bd3e17c5b 100644 --- a/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.ts +++ b/src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.ts @@ -42,6 +42,9 @@ export class OverlayKeyboardDispatcher implements OnDestroy { /** Add a new overlay to the list of attached overlay refs. */ add(overlayRef: OverlayRef): void { + // Ensure that we don't get the same overlay multiple times. + this.remove(overlayRef); + // Lazily start dispatcher once first overlay is added if (!this._isAttached) { this._document.body.addEventListener('keydown', this._keydownListener, true);