From 5148e3767e7f1e4351803f71cd7bffa22f19df45 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Tue, 18 Dec 2018 16:22:54 +0100 Subject: [PATCH] fix(overlay): not updating hasBackdrop after first open Along the same lines as #14561. The connected overlay directive has an input on whether it should have a backdrop, however we only use it the first time we create the backdrop. --- src/cdk/overlay/overlay-directives.spec.ts | 29 ++++++++++++++++++---- src/cdk/overlay/overlay-directives.ts | 19 +++++++------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/cdk/overlay/overlay-directives.spec.ts b/src/cdk/overlay/overlay-directives.spec.ts index 88794b0810f7..d55216ced68c 100644 --- a/src/cdk/overlay/overlay-directives.spec.ts +++ b/src/cdk/overlay/overlay-directives.spec.ts @@ -1,6 +1,6 @@ import {Component, ViewChild} from '@angular/core'; import {By} from '@angular/platform-browser'; -import {ComponentFixture, TestBed, async, inject} from '@angular/core/testing'; +import {ComponentFixture, TestBed, async, inject, fakeAsync, tick} from '@angular/core/testing'; import {Directionality} from '@angular/cdk/bidi'; import {dispatchKeyboardEvent} from '@angular/cdk/testing'; import {ESCAPE, A} from '@angular/cdk/keycodes'; @@ -210,18 +210,37 @@ describe('Overlay directives', () => { fixture.componentInstance.isOpen = true; fixture.detectChanges(); - let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop'); - expect(backdrop).toBeTruthy(); + expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeTruthy(); }); it('should not create the backdrop by default', () => { fixture.componentInstance.isOpen = true; fixture.detectChanges(); - let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop'); - expect(backdrop).toBeNull(); + expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeNull(); }); + it('should be able to change hasBackdrop after the overlay has been initialized', + fakeAsync(() => { + // Open once with a backdrop + fixture.componentInstance.hasBackdrop = true; + fixture.componentInstance.isOpen = true; + fixture.detectChanges(); + + expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeTruthy(); + + fixture.componentInstance.isOpen = false; + fixture.detectChanges(); + tick(500); + + // Open again without a backdrop. + fixture.componentInstance.hasBackdrop = false; + fixture.componentInstance.isOpen = true; + fixture.detectChanges(); + + expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeFalsy(); + })); + it('should set the custom backdrop class', () => { fixture.componentInstance.hasBackdrop = true; fixture.componentInstance.isOpen = true; diff --git a/src/cdk/overlay/overlay-directives.ts b/src/cdk/overlay/overlay-directives.ts index 8545bdb34638..cb67cde56db4 100644 --- a/src/cdk/overlay/overlay-directives.ts +++ b/src/cdk/overlay/overlay-directives.ts @@ -237,7 +237,11 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { } ngOnDestroy() { - this._destroyOverlay(); + if (this._overlayRef) { + this._overlayRef.dispose(); + } + + this._backdropSubscription.unsubscribe(); } ngOnChanges(changes: SimpleChanges) { @@ -351,6 +355,8 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { height: this.height, minHeight: this.minHeight, }); + + this._overlayRef.getConfig().hasBackdrop = this.hasBackdrop; } if (!this._overlayRef.hasAttached()) { @@ -362,6 +368,8 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { this._backdropSubscription = this._overlayRef.backdropClick().subscribe(event => { this.backdropClick.emit(event); }); + } else { + this._backdropSubscription.unsubscribe(); } } @@ -374,15 +382,6 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { this._backdropSubscription.unsubscribe(); } - - /** Destroys the overlay created by this directive. */ - private _destroyOverlay() { - if (this._overlayRef) { - this._overlayRef.dispose(); - } - - this._backdropSubscription.unsubscribe(); - } }