diff --git a/src/lib/core/overlay/overlay-ref.ts b/src/lib/core/overlay/overlay-ref.ts index 7894ca657251..f1deae352c6f 100644 --- a/src/lib/core/overlay/overlay-ref.ts +++ b/src/lib/core/overlay/overlay-ref.ts @@ -100,6 +100,7 @@ export class OverlayRef implements PortalHost { this.detachBackdrop(); this._portalHost.dispose(); this._attachments.complete(); + this._backdropClick.complete(); this._detachments.next(); this._detachments.complete(); } diff --git a/src/lib/core/overlay/overlay.spec.ts b/src/lib/core/overlay/overlay.spec.ts index f907a712200c..6c9b1494c932 100644 --- a/src/lib/core/overlay/overlay.spec.ts +++ b/src/lib/core/overlay/overlay.spec.ts @@ -327,6 +327,21 @@ describe('Overlay', () => { expect(backdropClickHandler).toHaveBeenCalled(); }); + it('should complete the backdrop click stream once the overlay is destroyed', () => { + let overlayRef = overlay.create(config); + + overlayRef.attach(componentPortal); + viewContainerFixture.detectChanges(); + + let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement; + let completeHandler = jasmine.createSpy('backdrop complete handler'); + + overlayRef.backdropClick().subscribe(null, null, completeHandler); + overlayRef.dispose(); + + expect(completeHandler).toHaveBeenCalled(); + }); + it('should apply the default overlay backdrop class', () => { let overlayRef = overlay.create(config); overlayRef.attach(componentPortal); diff --git a/src/lib/dialog/dialog-container.ts b/src/lib/dialog/dialog-container.ts index 0274c58379b8..ded0002e41cf 100644 --- a/src/lib/dialog/dialog-container.ts +++ b/src/lib/dialog/dialog-container.ts @@ -57,7 +57,7 @@ export function throwMdDialogContentAlreadyAttachedError() { ], host: { '[class.mat-dialog-container]': 'true', - '[attr.role]': 'dialogConfig?.role', + '[attr.role]': 'config?.role', '[@slideDialog]': '_state', '(@slideDialog.done)': '_onAnimationDone($event)', }, @@ -76,7 +76,7 @@ export class MdDialogContainer extends BasePortalHost { private _document: Document; /** The dialog configuration. */ - dialogConfig: MdDialogConfig; + config: MdDialogConfig; /** State of the dialog animation. */ _state: 'void' | 'enter' | 'exit' = 'enter'; diff --git a/src/lib/dialog/dialog-ref.ts b/src/lib/dialog/dialog-ref.ts index 36a6979c556d..3654acae1aa3 100644 --- a/src/lib/dialog/dialog-ref.ts +++ b/src/lib/dialog/dialog-ref.ts @@ -18,13 +18,16 @@ export class MdDialogRef { /** The instance of component opened into the dialog. */ componentInstance: T; + /** Whether the user is allowed to close the dialog. */ + disableClose: boolean = this._containerInstance.config.disableClose; + /** Subject for notifying the user that the dialog has finished closing. */ private _afterClosed: Subject = new Subject(); /** Result to be passed to afterClosed. */ private _result: any; - constructor(private _overlayRef: OverlayRef, public _containerInstance: MdDialogContainer) { + constructor(private _overlayRef: OverlayRef, private _containerInstance: MdDialogContainer) { _containerInstance._onAnimationStateChange .filter((event: AnimationEvent) => event.toState === 'exit') .subscribe(() => this._overlayRef.dispose(), null, () => { diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts index f1f9f539115a..c33c7bf70bde 100644 --- a/src/lib/dialog/dialog.spec.ts +++ b/src/lib/dialog/dialog.spec.ts @@ -451,6 +451,28 @@ describe('MdDialog', () => { expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy(); }); + + it('should allow for the disableClose option to be updated while open', async(() => { + let dialogRef = dialog.open(PizzaMsg, { + disableClose: true, + viewContainerRef: testViewContainerRef + }); + + viewContainerFixture.detectChanges(); + + let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement; + backdrop.click(); + + expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy(); + + dialogRef.disableClose = false; + backdrop.click(); + + viewContainerFixture.detectChanges(); + viewContainerFixture.whenStable().then(() => { + expect(overlayContainerElement.querySelector('md-dialog-container')).toBeFalsy(); + }); + })); }); describe('hasBackdrop option', () => { diff --git a/src/lib/dialog/dialog.ts b/src/lib/dialog/dialog.ts index abcc0c5a462d..85d2c8471054 100644 --- a/src/lib/dialog/dialog.ts +++ b/src/lib/dialog/dialog.ts @@ -16,7 +16,6 @@ import {MdDialogConfig} from './dialog-config'; import {MdDialogRef} from './dialog-ref'; import {MdDialogContainer} from './dialog-container'; import {TemplatePortal} from '../core/portal/portal'; -import 'rxjs/add/operator/first'; /** @@ -147,7 +146,7 @@ export class MdDialog { let containerPortal = new ComponentPortal(MdDialogContainer, viewContainer); let containerRef: ComponentRef = overlay.attach(containerPortal); - containerRef.instance.dialogConfig = config; + containerRef.instance.config = config; return containerRef.instance; } @@ -166,14 +165,18 @@ export class MdDialog { dialogContainer: MdDialogContainer, overlayRef: OverlayRef, config: MdDialogConfig): MdDialogRef { + // Create a reference to the dialog we're creating in order to give the user a handle // to modify and close it. - let dialogRef = new MdDialogRef(overlayRef, dialogContainer); - if (!config.disableClose) { - // When the dialog backdrop is clicked, we want to close it. - overlayRef.backdropClick().first().subscribe(() => dialogRef.close()); + // When the dialog backdrop is clicked, we want to close it. + if (config.hasBackdrop) { + overlayRef.backdropClick().subscribe(() => { + if (!dialogRef.disableClose) { + dialogRef.close(); + } + }); } // We create an injector specifically for the component we're instantiating so that it can @@ -221,7 +224,7 @@ export class MdDialog { */ private _handleKeydown(event: KeyboardEvent): void { let topDialog = this._openDialogs[this._openDialogs.length - 1]; - let canClose = topDialog ? !topDialog._containerInstance.dialogConfig.disableClose : false; + let canClose = topDialog ? !topDialog.disableClose : false; if (event.keyCode === ESCAPE && canClose) { topDialog.close();