diff --git a/src/cdk/overlay/overlay-ref.ts b/src/cdk/overlay/overlay-ref.ts index d1bd5c4657b9..45f5644a6f0a 100644 --- a/src/cdk/overlay/overlay-ref.ts +++ b/src/cdk/overlay/overlay-ref.ts @@ -95,6 +95,10 @@ export class OverlayRef implements PortalHost { * @returns The portal detachment result. */ detach(): any { + if (!this.hasAttached()) { + return; + } + this.detachBackdrop(); // When the overlay is detached, the pane element should disable pointer events. @@ -122,6 +126,8 @@ export class OverlayRef implements PortalHost { * Cleans up the overlay from the DOM. */ dispose(): void { + const isAttached = this.hasAttached(); + if (this._config.positionStrategy) { this._config.positionStrategy.dispose(); } @@ -134,7 +140,11 @@ export class OverlayRef implements PortalHost { this._portalHost.dispose(); this._attachments.complete(); this._backdropClick.complete(); - this._detachments.next(); + + if (isAttached) { + this._detachments.next(); + } + this._detachments.complete(); } diff --git a/src/cdk/overlay/overlay.spec.ts b/src/cdk/overlay/overlay.spec.ts index b5b35cc15ba9..b3fb79897842 100644 --- a/src/cdk/overlay/overlay.spec.ts +++ b/src/cdk/overlay/overlay.spec.ts @@ -177,6 +177,26 @@ describe('Overlay', () => { expect(spy).toHaveBeenCalled(); }); + it('should not emit to the detach stream if the overlay has not been attached', () => { + let overlayRef = overlay.create(); + let spy = jasmine.createSpy('detachments spy'); + + overlayRef.detachments().subscribe(spy); + overlayRef.detach(); + + expect(spy).not.toHaveBeenCalled(); + }); + + it('should not emit to the detach stream on dispose if the overlay was not attached', () => { + let overlayRef = overlay.create(); + let spy = jasmine.createSpy('detachments spy'); + + overlayRef.detachments().subscribe(spy); + overlayRef.dispose(); + + expect(spy).not.toHaveBeenCalled(); + }); + it('should emit the detachment event after the overlay is removed from the DOM', () => { let overlayRef = overlay.create();