diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts index af50e26c4ae8..420bdf80ba60 100644 --- a/src/lib/dialog/dialog.spec.ts +++ b/src/lib/dialog/dialog.spec.ts @@ -18,6 +18,8 @@ import { } from '@angular/core'; import {By} from '@angular/platform-browser'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {Location} from '@angular/common'; +import {SpyLocation} from '@angular/common/testing'; import {MdDialogModule} from './index'; import {MdDialog} from './dialog'; import {MdDialogContainer} from './dialog-container'; @@ -33,6 +35,7 @@ describe('MdDialog', () => { let testViewContainerRef: ViewContainerRef; let viewContainerFixture: ComponentFixture; + let mockLocation: SpyLocation; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -41,15 +44,17 @@ describe('MdDialog', () => { {provide: OverlayContainer, useFactory: () => { overlayContainerElement = document.createElement('div'); return {getContainerElement: () => overlayContainerElement}; - }} + }}, + {provide: Location, useClass: SpyLocation} ], }); TestBed.compileComponents(); })); - beforeEach(inject([MdDialog], (d: MdDialog) => { + beforeEach(inject([MdDialog, Location], (d: MdDialog, l: Location) => { dialog = d; + mockLocation = l as SpyLocation; })); beforeEach(() => { @@ -334,6 +339,34 @@ describe('MdDialog', () => { expect(dialogContainer._state).toBe('exit'); }); + it('should close all dialogs when the user goes forwards/backwards in history', async(() => { + dialog.open(PizzaMsg); + dialog.open(PizzaMsg); + + expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(2); + + mockLocation.simulateUrlPop(''); + viewContainerFixture.detectChanges(); + + viewContainerFixture.whenStable().then(() => { + expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(0); + }); + })); + + it('should close all open dialogs when the location hash changes', async(() => { + dialog.open(PizzaMsg); + dialog.open(PizzaMsg); + + expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(2); + + mockLocation.simulateHashChange(''); + viewContainerFixture.detectChanges(); + + viewContainerFixture.whenStable().then(() => { + expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(0); + }); + })); + describe('passing in data', () => { it('should be able to pass in data', () => { let config = { @@ -540,7 +573,8 @@ describe('MdDialog with a parent MdDialog', () => { {provide: OverlayContainer, useFactory: () => { overlayContainerElement = document.createElement('div'); return {getContainerElement: () => overlayContainerElement}; - }} + }}, + {provide: Location, useClass: SpyLocation} ], }); diff --git a/src/lib/dialog/dialog.ts b/src/lib/dialog/dialog.ts index bc828b62d317..2ce3d3cf816e 100644 --- a/src/lib/dialog/dialog.ts +++ b/src/lib/dialog/dialog.ts @@ -1,4 +1,5 @@ import {Injector, ComponentRef, Injectable, Optional, SkipSelf, TemplateRef} from '@angular/core'; +import {Location} from '@angular/common'; import {Observable} from 'rxjs/Observable'; import {Subject} from 'rxjs/Subject'; import {Overlay, OverlayRef, ComponentType, OverlayState, ComponentPortal} from '../core'; @@ -47,7 +48,16 @@ export class MdDialog { constructor( private _overlay: Overlay, private _injector: Injector, - @Optional() @SkipSelf() private _parentDialog: MdDialog) { } + @Optional() private _location: Location, + @Optional() @SkipSelf() private _parentDialog: MdDialog) { + + // Close all of the dialogs when the user goes forwards/backwards in history or when the + // location hash changes. Note that this usually doesn't include clicking on links (unless + // the user is using the `HashLocationStrategy`). + if (!_parentDialog && _location) { + _location.subscribe(() => this.closeAll()); + } + } /** * Opens a modal dialog containing the given component. diff --git a/src/lib/dialog/index.ts b/src/lib/dialog/index.ts index 664f8e4b0ab5..ee9a480b6396 100644 --- a/src/lib/dialog/index.ts +++ b/src/lib/dialog/index.ts @@ -1,4 +1,5 @@ import {NgModule, ModuleWithProviders} from '@angular/core'; +import {CommonModule} from '@angular/common'; import { OverlayModule, PortalModule, @@ -17,6 +18,7 @@ import { @NgModule({ imports: [ + CommonModule, OverlayModule, PortalModule, A11yModule,