Skip to content

Commit 7e1bb72

Browse files
committed
feat(dialog): allow disableClose option to be updated
* Exposes the disableClose option via the `MdDialogRef` and allows for it to be updated. * Makes the `containerInstance` private to `MdDialogRef` since it doesn't make sense for it to be public anymore. * Completes the `backdropClick` observable once the associated `overlayRef` is destroyed. This avoids having to unsubscribe manually or having to use `Observable.first`. Fixes #3938.
1 parent c8b1e20 commit 7e1bb72

File tree

6 files changed

+54
-10
lines changed

6 files changed

+54
-10
lines changed

src/lib/core/overlay/overlay-ref.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export class OverlayRef implements PortalHost {
9696
this._detachments.next();
9797
this._detachments.complete();
9898
this._attachments.complete();
99+
this._backdropClick.complete();
99100
}
100101

101102
/**

src/lib/core/overlay/overlay.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,21 @@ describe('Overlay', () => {
284284
expect(backdropClickHandler).toHaveBeenCalled();
285285
});
286286

287+
it('should complete the backdrop click stream once the overlay is destroyed', () => {
288+
let overlayRef = overlay.create(config);
289+
290+
overlayRef.attach(componentPortal);
291+
viewContainerFixture.detectChanges();
292+
293+
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
294+
let completeHandler = jasmine.createSpy('backdrop complete handler');
295+
296+
overlayRef.backdropClick().subscribe(null, null, completeHandler);
297+
overlayRef.dispose();
298+
299+
expect(completeHandler).toHaveBeenCalled();
300+
});
301+
287302
it('should apply the default overlay backdrop class', () => {
288303
let overlayRef = overlay.create(config);
289304
overlayRef.attach(componentPortal);

src/lib/dialog/dialog-container.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function throwMdDialogContentAlreadyAttachedError() {
5757
],
5858
host: {
5959
'[class.mat-dialog-container]': 'true',
60-
'[attr.role]': 'dialogConfig?.role',
60+
'[attr.role]': 'config?.role',
6161
'[@slideDialog]': '_state',
6262
'(@slideDialog.done)': '_onAnimationDone($event)',
6363
},
@@ -76,7 +76,7 @@ export class MdDialogContainer extends BasePortalHost {
7676
private _document: Document;
7777

7878
/** The dialog configuration. */
79-
dialogConfig: MdDialogConfig;
79+
config: MdDialogConfig;
8080

8181
/** State of the dialog animation. */
8282
_state: 'void' | 'enter' | 'exit' = 'enter';

src/lib/dialog/dialog-ref.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ export class MdDialogRef<T> {
1818
/** The instance of component opened into the dialog. */
1919
componentInstance: T;
2020

21+
/** Whether the user is allowed to close the dialog. */
22+
disableClose: boolean = this._containerInstance.config.disableClose;
23+
2124
/** Subject for notifying the user that the dialog has finished closing. */
2225
private _afterClosed: Subject<any> = new Subject();
2326

2427
/** Result to be passed to afterClosed. */
2528
private _result: any;
2629

27-
constructor(private _overlayRef: OverlayRef, public _containerInstance: MdDialogContainer) {
30+
constructor(private _overlayRef: OverlayRef, private _containerInstance: MdDialogContainer) {
2831
_containerInstance._onAnimationStateChange
2932
.filter((event: AnimationEvent) => event.toState === 'exit')
3033
.subscribe(() => this._overlayRef.dispose(), null, () => {

src/lib/dialog/dialog.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,28 @@ describe('MdDialog', () => {
441441

442442
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy();
443443
});
444+
445+
it('should allow for the disableClose option to be updated while open', async(() => {
446+
let dialogRef = dialog.open(PizzaMsg, {
447+
disableClose: true,
448+
viewContainerRef: testViewContainerRef
449+
});
450+
451+
viewContainerFixture.detectChanges();
452+
453+
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
454+
backdrop.click();
455+
456+
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy();
457+
458+
dialogRef.disableClose = false;
459+
backdrop.click();
460+
461+
viewContainerFixture.detectChanges();
462+
viewContainerFixture.whenStable().then(() => {
463+
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeFalsy();
464+
});
465+
}));
444466
});
445467

446468
describe('hasBackdrop option', () => {

src/lib/dialog/dialog.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {MdDialogConfig} from './dialog-config';
1616
import {MdDialogRef} from './dialog-ref';
1717
import {MdDialogContainer} from './dialog-container';
1818
import {TemplatePortal} from '../core/portal/portal';
19-
import 'rxjs/add/operator/first';
2019

2120

2221
/**
@@ -146,7 +145,7 @@ export class MdDialog {
146145
let containerPortal = new ComponentPortal(MdDialogContainer, viewContainer);
147146

148147
let containerRef: ComponentRef<MdDialogContainer> = overlay.attach(containerPortal);
149-
containerRef.instance.dialogConfig = config;
148+
containerRef.instance.config = config;
150149

151150
return containerRef.instance;
152151
}
@@ -165,14 +164,18 @@ export class MdDialog {
165164
dialogContainer: MdDialogContainer,
166165
overlayRef: OverlayRef,
167166
config: MdDialogConfig): MdDialogRef<T> {
167+
168168
// Create a reference to the dialog we're creating in order to give the user a handle
169169
// to modify and close it.
170-
171170
let dialogRef = new MdDialogRef<T>(overlayRef, dialogContainer);
172171

173-
if (!config.disableClose) {
174-
// When the dialog backdrop is clicked, we want to close it.
175-
overlayRef.backdropClick().first().subscribe(() => dialogRef.close());
172+
// When the dialog backdrop is clicked, we want to close it.
173+
if (config.hasBackdrop) {
174+
overlayRef.backdropClick().subscribe(() => {
175+
if (!dialogRef.disableClose) {
176+
dialogRef.close();
177+
}
178+
});
176179
}
177180

178181
// We create an injector specifically for the component we're instantiating so that it can
@@ -220,7 +223,7 @@ export class MdDialog {
220223
*/
221224
private _handleKeydown(event: KeyboardEvent): void {
222225
let topDialog = this._openDialogs[this._openDialogs.length - 1];
223-
let canClose = topDialog ? !topDialog._containerInstance.dialogConfig.disableClose : false;
226+
let canClose = topDialog ? !topDialog.disableClose : false;
224227

225228
if (event.keyCode === ESCAPE && canClose) {
226229
topDialog.close();

0 commit comments

Comments
 (0)