Skip to content

Commit

Permalink
feat(dialog): allow disableClose option to be updated (#4964)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
crisbeto authored and andrewseguin committed Jun 8, 2017
1 parent 657f0e8 commit 66629cf
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/lib/core/overlay/overlay-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export class OverlayRef implements PortalHost {
this.detachBackdrop();
this._portalHost.dispose();
this._attachments.complete();
this._backdropClick.complete();
this._detachments.next();
this._detachments.complete();
}
Expand Down
15 changes: 15 additions & 0 deletions src/lib/core/overlay/overlay.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,21 @@ describe('Overlay', () => {
expect(backdropClickHandler).toHaveBeenCalled();
});

it('should complete the backdrop click stream once the overlay is destroyed', () => {
let overlayRef = overlay.create(config);

overlayRef.attach(componentPortal);
viewContainerFixture.detectChanges();

let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
let completeHandler = jasmine.createSpy('backdrop complete handler');

overlayRef.backdropClick().subscribe(null, null, completeHandler);
overlayRef.dispose();

expect(completeHandler).toHaveBeenCalled();
});

it('should apply the default overlay backdrop class', () => {
let overlayRef = overlay.create(config);
overlayRef.attach(componentPortal);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/dialog/dialog-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function throwMdDialogContentAlreadyAttachedError() {
],
host: {
'[class.mat-dialog-container]': 'true',
'[attr.role]': 'dialogConfig?.role',
'[attr.role]': 'config?.role',
'[@slideDialog]': '_state',
'(@slideDialog.done)': '_onAnimationDone($event)',
},
Expand All @@ -76,7 +76,7 @@ export class MdDialogContainer extends BasePortalHost {
private _document: Document;

/** The dialog configuration. */
dialogConfig: MdDialogConfig;
config: MdDialogConfig;

/** State of the dialog animation. */
_state: 'void' | 'enter' | 'exit' = 'enter';
Expand Down
5 changes: 4 additions & 1 deletion src/lib/dialog/dialog-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ export class MdDialogRef<T> {
/** The instance of component opened into the dialog. */
componentInstance: T;

/** Whether the user is allowed to close the dialog. */
disableClose: boolean = this._containerInstance.config.disableClose;

/** Subject for notifying the user that the dialog has finished closing. */
private _afterClosed: Subject<any> = new Subject();

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

constructor(private _overlayRef: OverlayRef, public _containerInstance: MdDialogContainer) {
constructor(private _overlayRef: OverlayRef, private _containerInstance: MdDialogContainer) {
_containerInstance._onAnimationStateChange
.filter((event: AnimationEvent) => event.toState === 'exit')
.subscribe(() => this._overlayRef.dispose(), null, () => {
Expand Down
22 changes: 22 additions & 0 deletions src/lib/dialog/dialog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,28 @@ describe('MdDialog', () => {

expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy();
});

it('should allow for the disableClose option to be updated while open', async(() => {
let dialogRef = dialog.open(PizzaMsg, {
disableClose: true,
viewContainerRef: testViewContainerRef
});

viewContainerFixture.detectChanges();

let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
backdrop.click();

expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy();

dialogRef.disableClose = false;
backdrop.click();

viewContainerFixture.detectChanges();
viewContainerFixture.whenStable().then(() => {
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeFalsy();
});
}));
});

describe('hasBackdrop option', () => {
Expand Down
17 changes: 10 additions & 7 deletions src/lib/dialog/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {MdDialogConfig} from './dialog-config';
import {MdDialogRef} from './dialog-ref';
import {MdDialogContainer} from './dialog-container';
import {TemplatePortal} from '../core/portal/portal';
import 'rxjs/add/operator/first';


/**
Expand Down Expand Up @@ -147,7 +146,7 @@ export class MdDialog {
let containerPortal = new ComponentPortal(MdDialogContainer, viewContainer);

let containerRef: ComponentRef<MdDialogContainer> = overlay.attach(containerPortal);
containerRef.instance.dialogConfig = config;
containerRef.instance.config = config;

return containerRef.instance;
}
Expand All @@ -166,14 +165,18 @@ export class MdDialog {
dialogContainer: MdDialogContainer,
overlayRef: OverlayRef,
config: MdDialogConfig): MdDialogRef<T> {

// Create a reference to the dialog we're creating in order to give the user a handle
// to modify and close it.

let dialogRef = new MdDialogRef<T>(overlayRef, dialogContainer);

if (!config.disableClose) {
// When the dialog backdrop is clicked, we want to close it.
overlayRef.backdropClick().first().subscribe(() => dialogRef.close());
// When the dialog backdrop is clicked, we want to close it.
if (config.hasBackdrop) {
overlayRef.backdropClick().subscribe(() => {
if (!dialogRef.disableClose) {
dialogRef.close();
}
});
}

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

if (event.keyCode === ESCAPE && canClose) {
topDialog.close();
Expand Down

0 comments on commit 66629cf

Please sign in to comment.