Skip to content

Commit 4e08418

Browse files
committed
feat(dialog): allow for closing on navigation to be disabled
Allows consumers to opt out of the functionality that closes all of the open dialogs when going backwards/forwards in history. Fixes #8983.
1 parent d85c44b commit 4e08418

File tree

4 files changed

+37
-11
lines changed

4 files changed

+37
-11
lines changed

src/lib/dialog/dialog-config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,8 @@ export class MatDialogConfig<D = any> {
9898
/** Scroll strategy to be used for the dialog. */
9999
scrollStrategy?: ScrollStrategy;
100100

101+
/** Whether the dialog should close when the user goes backwards/forwards in history. */
102+
closeOnNavigation?: boolean = true;
103+
101104
// TODO(jelbourn): add configuration for lifecycle hooks, ARIA labelling.
102105
}

src/lib/dialog/dialog-ref.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88

99
import {OverlayRef, GlobalPositionStrategy} from '@angular/cdk/overlay';
1010
import {ESCAPE} from '@angular/cdk/keycodes';
11+
import {Location} from '@angular/common';
1112
import {filter} from 'rxjs/operators/filter';
1213
import {take} from 'rxjs/operators/take';
1314
import {DialogPosition} from './dialog-config';
1415
import {Observable} from 'rxjs/Observable';
1516
import {Subject} from 'rxjs/Subject';
17+
import {Subscription, ISubscription} from 'rxjs/Subscription';
1618
import {MatDialogContainer} from './dialog-container';
1719

1820

@@ -43,9 +45,13 @@ export class MatDialogRef<T, R = any> {
4345
/** Result to be passed to afterClosed. */
4446
private _result: R | undefined;
4547

48+
/** Subscription to changes in the user's location. */
49+
private _locationChanges: ISubscription = Subscription.EMPTY;
50+
4651
constructor(
4752
private _overlayRef: OverlayRef,
4853
private _containerInstance: MatDialogContainer,
54+
location?: Location,
4955
readonly id: string = `mat-dialog-${uniqueId++}`) {
5056

5157
// Emit when opening animation completes
@@ -65,6 +71,7 @@ export class MatDialogRef<T, R = any> {
6571
)
6672
.subscribe(() => {
6773
this._overlayRef.dispose();
74+
this._locationChanges.unsubscribe();
6875
this._afterClosed.next(this._result);
6976
this._afterClosed.complete();
7077
this.componentInstance = null!;
@@ -73,6 +80,17 @@ export class MatDialogRef<T, R = any> {
7380
_overlayRef.keydownEvents()
7481
.pipe(filter(event => event.keyCode === ESCAPE && !this.disableClose))
7582
.subscribe(() => this.close());
83+
84+
if (location) {
85+
// Close the dialog when the user goes forwards/backwards in history or when the location
86+
// hash changes. Note that this usually doesn't include clicking on links (unless the user
87+
// is using the `HashLocationStrategy`).
88+
this._locationChanges = location.subscribe(() => {
89+
if (this._containerInstance._config.closeOnNavigation) {
90+
this.close();
91+
}
92+
});
93+
}
7694
}
7795

7896
/**

src/lib/dialog/dialog.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,19 @@ describe('MatDialog', () => {
582582
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(0);
583583
}));
584584

585+
it('should allow the consumer to disable closing a dialog on navigation', fakeAsync(() => {
586+
dialog.open(PizzaMsg);
587+
dialog.open(PizzaMsg, {closeOnNavigation: false});
588+
589+
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(2);
590+
591+
mockLocation.simulateUrlPop('');
592+
viewContainerFixture.detectChanges();
593+
flush();
594+
595+
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(1);
596+
}));
597+
585598
it('should have the componentInstance available in the afterClosed callback', fakeAsync(() => {
586599
let dialogRef = dialog.open(PizzaMsg);
587600
let spy = jasmine.createSpy('afterClosed spy');

src/lib/dialog/dialog.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,11 @@ export class MatDialog {
9696
constructor(
9797
private _overlay: Overlay,
9898
private _injector: Injector,
99-
@Optional() location: Location,
99+
@Optional() private _location: Location,
100100
@Optional() @Inject(MAT_DIALOG_DEFAULT_OPTIONS) private _defaultOptions,
101101
@Inject(MAT_DIALOG_SCROLL_STRATEGY) private _scrollStrategy,
102102
@Optional() @SkipSelf() private _parentDialog: MatDialog,
103-
private _overlayContainer: OverlayContainer) {
104-
105-
// Close all of the dialogs when the user goes forwards/backwards in history or when the
106-
// location hash changes. Note that this usually doesn't include clicking on links (unless
107-
// the user is using the `HashLocationStrategy`).
108-
if (!_parentDialog && location) {
109-
location.subscribe(() => this.closeAll());
110-
}
111-
}
103+
private _overlayContainer: OverlayContainer) {}
112104

113105
/**
114106
* Opens a modal dialog containing the given component.
@@ -232,7 +224,7 @@ export class MatDialog {
232224

233225
// Create a reference to the dialog we're creating in order to give the user a handle
234226
// to modify and close it.
235-
const dialogRef = new MatDialogRef<T>(overlayRef, dialogContainer, config.id);
227+
const dialogRef = new MatDialogRef<T>(overlayRef, dialogContainer, this._location, config.id);
236228

237229
// When the dialog backdrop is clicked, we want to close it.
238230
if (config.hasBackdrop) {

0 commit comments

Comments
 (0)