Skip to content

Commit 6506b10

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 cebb516 commit 6506b10

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
@@ -91,6 +91,7 @@ export class OverlayRef implements PortalHost {
9191
this._detachments.next();
9292
this._detachments.complete();
9393
this._attachments.complete();
94+
this._backdropClick.complete();
9495
}
9596

9697
/**

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
@@ -53,7 +53,7 @@ export function throwMdDialogContentAlreadyAttachedError() {
5353
],
5454
host: {
5555
'[class.mat-dialog-container]': 'true',
56-
'[attr.role]': 'dialogConfig?.role',
56+
'[attr.role]': 'config?.role',
5757
'[@slideDialog]': '_state',
5858
'(@slideDialog.done)': '_onAnimationDone($event)',
5959
},
@@ -72,7 +72,7 @@ export class MdDialogContainer extends BasePortalHost {
7272
private _document: Document;
7373

7474
/** The dialog configuration. */
75-
dialogConfig: MdDialogConfig;
75+
config: MdDialogConfig;
7676

7777
/** State of the dialog animation. */
7878
_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(() => {

src/lib/dialog/dialog.spec.ts

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

430430
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy();
431431
});
432+
433+
it('should allow for the disableClose option to be updated while open', async(() => {
434+
let dialogRef = dialog.open(PizzaMsg, {
435+
disableClose: true,
436+
viewContainerRef: testViewContainerRef
437+
});
438+
439+
viewContainerFixture.detectChanges();
440+
441+
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
442+
backdrop.click();
443+
444+
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy();
445+
446+
dialogRef.disableClose = false;
447+
backdrop.click();
448+
449+
viewContainerFixture.detectChanges();
450+
viewContainerFixture.whenStable().then(() => {
451+
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeFalsy();
452+
});
453+
}));
432454
});
433455

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

src/lib/dialog/dialog.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {MdDialogContainer} from './dialog-container';
1212
import {TemplatePortal} from '../core/portal/portal';
1313
import {BlockScrollStrategy} from '../core/overlay/scroll/block-scroll-strategy';
1414
import {ViewportRuler} from '../core/overlay/position/viewport-ruler';
15-
import 'rxjs/add/operator/first';
1615

1716

1817
/**
@@ -143,7 +142,7 @@ export class MdDialog {
143142
let containerPortal = new ComponentPortal(MdDialogContainer, viewContainer);
144143

145144
let containerRef: ComponentRef<MdDialogContainer> = overlay.attach(containerPortal);
146-
containerRef.instance.dialogConfig = config;
145+
containerRef.instance.config = config;
147146

148147
return containerRef.instance;
149148
}
@@ -162,14 +161,18 @@ export class MdDialog {
162161
dialogContainer: MdDialogContainer,
163162
overlayRef: OverlayRef,
164163
config: MdDialogConfig): MdDialogRef<T> {
164+
165165
// Create a reference to the dialog we're creating in order to give the user a handle
166166
// to modify and close it.
167-
168167
let dialogRef = new MdDialogRef<T>(overlayRef, dialogContainer);
169168

170-
if (!config.disableClose) {
171-
// When the dialog backdrop is clicked, we want to close it.
172-
overlayRef.backdropClick().first().subscribe(() => dialogRef.close());
169+
// When the dialog backdrop is clicked, we want to close it.
170+
if (config.hasBackdrop) {
171+
overlayRef.backdropClick().subscribe(() => {
172+
if (!dialogRef.disableClose) {
173+
dialogRef.close();
174+
}
175+
});
173176
}
174177

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

222225
if (event.keyCode === ESCAPE && canClose) {
223226
topDialog.close();

0 commit comments

Comments
 (0)