diff --git a/src/lib/dialog/dialog-config.ts b/src/lib/dialog/dialog-config.ts index fa6d74fb6e26..83c41cb308b8 100644 --- a/src/lib/dialog/dialog-config.ts +++ b/src/lib/dialog/dialog-config.ts @@ -14,6 +14,8 @@ export class MdDialogConfig { /** The ARIA role of the dialog element. */ role: DialogRole = 'dialog'; - // TODO(jelbourn): add configuration for size, clickOutsideToClose, lifecycle hooks, - // ARIA labelling. + /** Whether the user can use escape or clicking outside to close a modal. */ + disableClose = false; + + // TODO(jelbourn): add configuration for size, lifecycle hooks, ARIA labelling. } diff --git a/src/lib/dialog/dialog-container.ts b/src/lib/dialog/dialog-container.ts index 5f920aa0d0ca..997d16996685 100644 --- a/src/lib/dialog/dialog-container.ts +++ b/src/lib/dialog/dialog-container.ts @@ -1,10 +1,11 @@ import { - Component, - ComponentRef, - ViewChild, - ViewEncapsulation, - NgZone, - OnDestroy + Component, + ComponentRef, + ViewChild, + ViewEncapsulation, + NgZone, + OnDestroy, + ElementRef } from '@angular/core'; import {BasePortalHost, ComponentPortal, PortalHostDirective, TemplatePortal} from '../core'; import {MdDialogConfig} from './dialog-config'; @@ -25,7 +26,7 @@ import 'rxjs/add/operator/first'; host: { 'class': 'md-dialog-container', '[attr.role]': 'dialogConfig?.role', - '(keydown.escape)': 'handleEscapeKey()', + '(keydown.escape)': 'handleEscapeKey()' }, encapsulation: ViewEncapsulation.None, }) @@ -45,7 +46,7 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy { /** Reference to the open dialog. */ dialogRef: MdDialogRef; - constructor(private _ngZone: NgZone) { + constructor(private _ngZone: NgZone, public elementRef: ElementRef) { super(); } @@ -74,8 +75,9 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy { /** Handles the user pressing the Escape key. */ handleEscapeKey() { - // TODO(jelbourn): add MdDialogConfig option to disable this behavior. - this.dialogRef.close(); + if (!this.dialogConfig.disableClose) { + this.dialogRef.close(); + } } ngOnDestroy() { diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts index 6ff5b8651ee8..1477cc0bff31 100644 --- a/src/lib/dialog/dialog.spec.ts +++ b/src/lib/dialog/dialog.spec.ts @@ -128,6 +128,40 @@ describe('MdDialog', () => { expect(overlayContainerElement.querySelector('md-dialog-container')).toBeFalsy(); }); + describe('disableClose option', () => { + it('should prevent closing via clicks on the backdrop', () => { + let config = new MdDialogConfig(); + config.viewContainerRef = testViewContainerRef; + config.disableClose = true; + + dialog.open(PizzaMsg, config); + + viewContainerFixture.detectChanges(); + + let backdrop = overlayContainerElement.querySelector('.md-overlay-backdrop'); + backdrop.click(); + + expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy(); + }); + + it('should prevent closing via the escape key', () => { + let config = new MdDialogConfig(); + config.viewContainerRef = testViewContainerRef; + config.disableClose = true; + + dialog.open(PizzaMsg, config); + + viewContainerFixture.detectChanges(); + + let dialogContainer: MdDialogContainer = viewContainerFixture.debugElement.query( + By.directive(MdDialogContainer)).componentInstance; + + dialogContainer.handleEscapeKey(); + + expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy(); + }); + }); + describe('focus management', () => { // When testing focus, all of the elements must be in the DOM. diff --git a/src/lib/dialog/dialog.ts b/src/lib/dialog/dialog.ts index 05384daecc78..c8539a7ecb83 100644 --- a/src/lib/dialog/dialog.ts +++ b/src/lib/dialog/dialog.ts @@ -87,8 +87,10 @@ export class MdDialog { // to modify and close it. let dialogRef = > new MdDialogRef(overlayRef); - // When the dialog backdrop is clicked, we want to close it. - overlayRef.backdropClick().first().subscribe(() => dialogRef.close()); + if (!dialogContainer.dialogConfig.disableClose) { + // When the dialog backdrop is clicked, we want to close it. + overlayRef.backdropClick().first().subscribe(() => dialogRef.close()); + } // Set the dialogRef to the container so that it can use the ref to close the dialog. dialogContainer.dialogRef = dialogRef;