Skip to content

Commit ccbfedc

Browse files
committed
fix(dialog): close all dialogs on popstate/hashchange
Closes all of the open dialogs when the user goes forwards/backwards in history. Fixes #2601.
1 parent aa3360a commit ccbfedc

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

src/lib/dialog/dialog.spec.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {NgModule,
1616
Inject,
1717
} from '@angular/core';
1818
import {By} from '@angular/platform-browser';
19+
import {Location} from '@angular/common';
20+
import {SpyLocation} from '@angular/common/testing';
1921
import {MdDialogModule} from './index';
2022
import {MdDialog} from './dialog';
2123
import {MdDialogContainer} from './dialog-container';
@@ -31,6 +33,7 @@ describe('MdDialog', () => {
3133

3234
let testViewContainerRef: ViewContainerRef;
3335
let viewContainerFixture: ComponentFixture<ComponentWithChildViewContainer>;
36+
let mockLocation: SpyLocation;
3437

3538
beforeEach(async(() => {
3639
TestBed.configureTestingModule({
@@ -39,15 +42,17 @@ describe('MdDialog', () => {
3942
{provide: OverlayContainer, useFactory: () => {
4043
overlayContainerElement = document.createElement('div');
4144
return {getContainerElement: () => overlayContainerElement};
42-
}}
45+
}},
46+
{provide: Location, useClass: SpyLocation}
4347
],
4448
});
4549

4650
TestBed.compileComponents();
4751
}));
4852

49-
beforeEach(inject([MdDialog], (d: MdDialog) => {
53+
beforeEach(inject([MdDialog, Location], (d: MdDialog, l: Location) => {
5054
dialog = d;
55+
mockLocation = l as SpyLocation;
5156
}));
5257

5358
beforeEach(() => {
@@ -323,6 +328,34 @@ describe('MdDialog', () => {
323328
});
324329
}));
325330

331+
it('should close all dialogs when the user goes forwards/backwards in history', async(() => {
332+
dialog.open(PizzaMsg);
333+
dialog.open(PizzaMsg);
334+
335+
expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(2);
336+
337+
mockLocation.simulateUrlPop('');
338+
viewContainerFixture.detectChanges();
339+
340+
viewContainerFixture.whenStable().then(() => {
341+
expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(0);
342+
});
343+
}));
344+
345+
it('should close all open dialogs when the location hash changes', async(() => {
346+
dialog.open(PizzaMsg);
347+
dialog.open(PizzaMsg);
348+
349+
expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(2);
350+
351+
mockLocation.simulateHashChange('');
352+
viewContainerFixture.detectChanges();
353+
354+
viewContainerFixture.whenStable().then(() => {
355+
expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(0);
356+
});
357+
}));
358+
326359
describe('passing in data', () => {
327360
it('should be able to pass in data', () => {
328361
let config = {
@@ -485,7 +518,8 @@ describe('MdDialog with a parent MdDialog', () => {
485518
{provide: OverlayContainer, useFactory: () => {
486519
overlayContainerElement = document.createElement('div');
487520
return {getContainerElement: () => overlayContainerElement};
488-
}}
521+
}},
522+
{provide: Location, useClass: SpyLocation}
489523
],
490524
});
491525

src/lib/dialog/dialog.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {Injector, ComponentRef, Injectable, Optional, SkipSelf, TemplateRef} from '@angular/core';
2+
import {Location} from '@angular/common';
23
import {Observable} from 'rxjs/Observable';
34
import {Subject} from 'rxjs/Subject';
45
import {Overlay, OverlayRef, ComponentType, OverlayState, ComponentPortal} from '../core';
@@ -46,7 +47,16 @@ export class MdDialog {
4647
constructor(
4748
private _overlay: Overlay,
4849
private _injector: Injector,
49-
@Optional() @SkipSelf() private _parentDialog: MdDialog) { }
50+
private _location: Location,
51+
@Optional() @SkipSelf() private _parentDialog: MdDialog) {
52+
53+
// Close all of the dialogs when the user goes forwards/backwards in history or when the
54+
// location hash changes. Note that this usually doesn't include clicking on links (unless
55+
// the user is using the `HashLocationStrategy`).
56+
if (!_parentDialog) {
57+
_location.subscribe(() => this.closeAll());
58+
}
59+
}
5060

5161
/**
5262
* Opens a modal dialog containing the given component.

src/lib/dialog/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {NgModule, ModuleWithProviders} from '@angular/core';
2+
import {CommonModule} from '@angular/common';
23
import {
34
OverlayModule,
45
PortalModule,
@@ -17,6 +18,7 @@ import {
1718

1819
@NgModule({
1920
imports: [
21+
CommonModule,
2022
OverlayModule,
2123
PortalModule,
2224
A11yModule,

0 commit comments

Comments
 (0)