diff --git a/src/lib/dialog/README.md b/src/lib/dialog/README.md index b9fb3c3c1506..d68f89f54aff 100644 --- a/src/lib/dialog/README.md +++ b/src/lib/dialog/README.md @@ -7,6 +7,7 @@ MdDialog is a service, which opens dialogs components in the view. | Name | Description | | --- | --- | | `open(component: ComponentType, config: MdDialogConfig): MdDialogRef` | Creates and opens a dialog matching material spec. | +| `closeAll(): void` | Closes all of the dialogs that are currently open. | ### Config diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts index 7b797627541e..34855db3f59a 100644 --- a/src/lib/dialog/dialog.spec.ts +++ b/src/lib/dialog/dialog.spec.ts @@ -214,6 +214,18 @@ describe('MdDialog', () => { expect(overlayPane.style.marginRight).toBe('125px'); }); + it('should close all of the dialogs', () => { + dialog.open(PizzaMsg); + dialog.open(PizzaMsg); + dialog.open(PizzaMsg); + + expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(3); + + dialog.closeAll(); + + expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(0); + }); + describe('disableClose option', () => { it('should prevent closing via clicks on the backdrop', () => { dialog.open(PizzaMsg, { diff --git a/src/lib/dialog/dialog.ts b/src/lib/dialog/dialog.ts index b2d75f84c819..fe15864617af 100644 --- a/src/lib/dialog/dialog.ts +++ b/src/lib/dialog/dialog.ts @@ -23,7 +23,6 @@ export {MdDialogRef} from './dialog-ref'; // TODO(jelbourn): add support for opening with a TemplateRef -// TODO(jelbourn): add `closeAll` method // TODO(jelbourn): dialog content directives (e.g., md-dialog-header) // TODO(jelbourn): animations @@ -34,6 +33,9 @@ export {MdDialogRef} from './dialog-ref'; */ @Injectable() export class MdDialog { + /** Keeps track of the currently-open dialogs. */ + private _openDialogs: MdDialogRef[] = []; + constructor(private _overlay: Overlay, private _injector: Injector) { } /** @@ -46,8 +48,27 @@ export class MdDialog { let overlayRef = this._createOverlay(config); let dialogContainer = this._attachDialogContainer(overlayRef, config); + let dialogRef = this._attachDialogContent(component, dialogContainer, overlayRef); + + this._openDialogs.push(dialogRef); + dialogRef.afterClosed().subscribe(() => this._removeOpenDialog(dialogRef)); - return this._attachDialogContent(component, dialogContainer, overlayRef); + return dialogRef; + } + + /** + * Closes all of the currently-open dialogs. + */ + closeAll(): void { + let i = this._openDialogs.length; + + while (i--) { + // The `_openDialogs` property isn't updated after close until the rxjs subscription + // runs on the next microtask, in addition to modifying the array as we're going + // through it. We loop through all of them and call close without assuming that + // they'll be removed from the list instantaneously. + this._openDialogs[i].close(); + } } /** @@ -141,6 +162,17 @@ export class MdDialog { return state; } + + /** + * Removes a dialog from the array of open dialogs. + */ + private _removeOpenDialog(dialogRef: MdDialogRef) { + let index = this._openDialogs.indexOf(dialogRef); + + if (index > -1) { + this._openDialogs.splice(index, 1); + } + } } /**