Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/material/dialog/dialog-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class MatDialogConfig<D = any> {
result: Result | undefined,
config: Config,
componentInstance: Component | null,
) => boolean;
) => boolean | Promise<boolean>;

/** Width of the dialog. */
width?: string = '';
Expand Down
23 changes: 21 additions & 2 deletions src/material/dialog/dialog-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,29 @@ export class MatDialogRef<T, R = any> {
close(dialogResult?: R): void {
const closePredicate = this._config.closePredicate;

if (closePredicate && !closePredicate(dialogResult, this._config, this.componentInstance)) {
return;
if (closePredicate) {
const result = closePredicate(dialogResult, this._config, this.componentInstance);

if (result instanceof Promise) {
result.then(canClose => {
if (canClose) {
this._performClose(dialogResult);
}
});
return;
} else if (!result) {
return;
}
}

this._performClose(dialogResult);
}

/**
* Performs the actual dialog close operation.
* @param dialogResult Optional result to return to the dialog opener.
*/
private _performClose(dialogResult?: R): void {
this._result = dialogResult;

// Transition the backdrop in parallel to the dialog.
Expand Down
44 changes: 44 additions & 0 deletions src/material/dialog/dialog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,50 @@ describe('MatDialog', () => {

overlayContainerElement.remove();
}));

it('should support async closePredicate that returns a Promise', fakeAsync(() => {
let resolvePromise: (value: boolean) => void;
const closedSpy = jasmine.createSpy('closed spy');
const ref = dialog.open(PizzaMsg, {
closePredicate: () =>
new Promise<boolean>(resolve => {
resolvePromise = resolve;
}),
viewContainerRef: testViewContainerRef,
});

ref.afterClosed().subscribe(closedSpy);
viewContainerFixture.detectChanges();

expect(getDialogs().length).toBe(1);

// Try to close - should not close immediately
ref.close('test-result');
viewContainerFixture.detectChanges();
flush();

expect(getDialogs().length).toBe(1);
expect(closedSpy).not.toHaveBeenCalled();

// Resolve promise with false - should still not close
resolvePromise!(false);
tick();
viewContainerFixture.detectChanges();
flush();

expect(getDialogs().length).toBe(1);
expect(closedSpy).not.toHaveBeenCalled();

// Try to close again and resolve with true - should close
ref.close('test-result');
resolvePromise!(true);
tick();
viewContainerFixture.detectChanges();
flush();

expect(getDialogs().length).toBe(0);
expect(closedSpy).toHaveBeenCalledWith('test-result');
}));
});

it(
Expand Down
Loading