diff --git a/components/modal/nz-modal.component.html b/components/modal/nz-modal.component.html
index 552adb92d54..be423e10b5f 100644
--- a/components/modal/nz-modal.component.html
+++ b/components/modal/nz-modal.component.html
@@ -10,6 +10,7 @@
>
extends NzModalRef
private focusTrap: FocusTrap;
private scrollStrategy: BlockScrollStrategy;
private overlayRef: OverlayRef;
+ private dialogMouseDown = false;
+ private timeoutId: number;
[key: string]: any; // tslint:disable-line:no-any
@@ -260,6 +263,7 @@ export class NzModalComponent extends NzModalRef
this.unsubscribe$.next();
this.unsubscribe$.complete();
});
+ clearTimeout(this.timeoutId);
}
setOverlayRef(overlayRef: OverlayRef): void {
@@ -309,12 +313,25 @@ export class NzModalComponent extends NzModalRef
return this.elementRef && this.elementRef.nativeElement;
}
+ onMaskDialogDown(): void {
+ this.dialogMouseDown = true;
+ }
+
+ onDialogUp(): void {
+ if (this.dialogMouseDown) {
+ this.timeoutId = setTimeout(() => {
+ this.dialogMouseDown = false;
+ }, 0);
+ }
+ }
+
onClickMask($event: MouseEvent): void {
if (
this.mask &&
this.maskClosable &&
- ($event.target as HTMLElement).classList.contains('ant-modal-wrap') &&
- this.nzVisible
+ ($event.target as HTMLElement).classList.contains(WRAP_CLASS_NAME) &&
+ this.nzVisible &&
+ !this.dialogMouseDown
) {
this.onClickOkCancel('cancel');
}
diff --git a/components/modal/nz-modal.spec.ts b/components/modal/nz-modal.spec.ts
index 2d9fb5563d4..324e16e0351 100644
--- a/components/modal/nz-modal.spec.ts
+++ b/components/modal/nz-modal.spec.ts
@@ -9,7 +9,7 @@ import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/t
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { NzButtonComponent, NzButtonModule } from 'ng-zorro-antd/button';
-import { dispatchKeyboardEvent, NzMeasureScrollbarService } from 'ng-zorro-antd/core';
+import { dispatchFakeEvent, dispatchKeyboardEvent, NzMeasureScrollbarService } from 'ng-zorro-antd/core';
import { NzI18nService } from 'ng-zorro-antd/i18n';
import { NzIconTestModule } from 'ng-zorro-antd/icon/testing';
import en_US from '../i18n/languages/en_US';
@@ -441,7 +441,7 @@ describe('NzModal', () => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, NzModalModule],
providers: [NzMeasureScrollbarService],
- declarations: [NzDemoModalBasicComponent, ModalByServiceComponent]
+ declarations: [NzDemoModalBasicComponent, NzDemoModalMaskComponent, ModalByServiceComponent]
});
TestBed.compileComponents();
@@ -672,6 +672,44 @@ describe('NzModal', () => {
document.body.removeChild(forceScrollElement);
}));
});
+
+ describe('close with mask', () => {
+ let fixture: ComponentFixture;
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NzDemoModalMaskComponent);
+ });
+
+ it('should close when mask click', fakeAsync(() => {
+ fixture.componentInstance.isVisible = true;
+ fixture.detectChanges();
+ tick(1000);
+ fixture.detectChanges();
+ const nativeElement = fixture.debugElement.query(By.css('.ant-modal-wrap')).nativeElement;
+ fixture.detectChanges();
+ nativeElement!.click();
+ fixture.detectChanges();
+ tick(1000);
+ fixture.detectChanges();
+ expectModalHidden(fixture.debugElement.query(By.css('nz-modal')).nativeElement, true);
+ }));
+
+ it('should not close if mouse down in dialog', fakeAsync(() => {
+ fixture.componentInstance.isVisible = true;
+ fixture.detectChanges();
+ tick(1000);
+ fixture.detectChanges();
+ const bodyNativeElement = fixture.debugElement.query(By.css('.ant-modal-body')).nativeElement;
+ dispatchFakeEvent(bodyNativeElement, 'mousedown');
+ fixture.detectChanges();
+ const warpNativeElement = fixture.debugElement.query(By.css('.ant-modal-wrap')).nativeElement;
+ dispatchFakeEvent(warpNativeElement, 'mouseup');
+ dispatchFakeEvent(warpNativeElement, 'click');
+ fixture.detectChanges();
+ tick(1000);
+ fixture.detectChanges();
+ expectModalHidden(fixture.debugElement.query(By.css('nz-modal')).nativeElement, false);
+ }));
+ });
});
// -------------------------------------------
@@ -689,6 +727,20 @@ class NzDemoModalBasicComponent {
modalAvailable = true;
}
+@Component({
+ template: `
+
+ content
+
+ `
+})
+class NzDemoModalMaskComponent {
+ isVisible = false;
+ handleCancel(): void {
+ this.isVisible = false;
+ }
+}
+
@Component({
template: `