diff --git a/components/drawer/doc/index.en-US.md b/components/drawer/doc/index.en-US.md index f8613655a86..093cb0eebe4 100755 --- a/components/drawer/doc/index.en-US.md +++ b/components/drawer/doc/index.en-US.md @@ -56,6 +56,7 @@ import { NzDrawerModule } from 'ng-zorro-antd'; | nzContent | The drawer body content. | `TemplateRef<{ $implicit: D, drawerRef: NzDrawerRef }>|Type` | - | | nzContentParams | The component inputs the param / The Template context. | `D` | - | | nzClosable | Whether a close (x) button is visible on top right of the Drawer dialog or not. | `boolean` | `true` | +| nzOnCancel | Execute when click on the mask or the upper cancel button, This function returns a promise, which is automatically closed when the execution is complete or the promise ends (return false to prevent closing) | `() => Promise` | - | | nzMaskClosable | Clicking on the mask (area outside the Drawer) to close the Drawer or not. | `boolean` | `true` | | nzMask | Whether to show mask or not. | `boolean` | `true` | | nzMaskStyle | Style for Drawer's mask element. | `object` | `{}` | diff --git a/components/drawer/doc/index.zh-CN.md b/components/drawer/doc/index.zh-CN.md index 30876c03ca6..ccb8dc84d78 100755 --- a/components/drawer/doc/index.zh-CN.md +++ b/components/drawer/doc/index.zh-CN.md @@ -42,7 +42,7 @@ import { NzDrawerModule } from 'ng-zorro-antd'; | `[nzOffsetY]` | y 坐标移量(px), 高度, 只在方向为 `'top'`或`'bottom'` 时生效 | `number` | `0` | | `[nzWrapClassName]` | 对话框外层容器的类名 | `string` | - | | `[nzZIndex]` | 设置 Drawer 的 `z-index` | `number` | `1000` | -| `(nzOnClose)` | 点击遮罩层或右上角叉或取消按钮的回调 | `EventEmitter` | - | +| `(nzOnClose)` | 点击遮罩层或右上角叉的回调 | `EventEmitter` | - | ### NzDrawerService @@ -56,6 +56,7 @@ import { NzDrawerModule } from 'ng-zorro-antd'; | --- | --- | --- | --- | | nzContent | Drawer body 的内容 | `TemplateRef<{ $implicit: D, drawerRef: NzDrawerRef }>| Type` | - | | nzContentParams | 内容组件的输入参数 / Template的 context | `D` | - | +| nzOnCancel | 点击遮罩层或右上角叉时执行,该函数可返回 promise 待执行完毕或 promise 结束时,将自动关闭对话框(返回false可阻止关闭) | `() => Promise` | - | | nzClosable | 是否显示右上角的关闭按钮 | `boolean` | `true` | | nzMaskClosable | 点击蒙层是否允许关闭 | `boolean` | `true` | | nzMask | 是否展示遮罩 | `boolean` | `true` | diff --git a/components/drawer/nz-drawer-options.ts b/components/drawer/nz-drawer-options.ts index c36307ad12d..8cce2b4d8d9 100644 --- a/components/drawer/nz-drawer-options.ts +++ b/components/drawer/nz-drawer-options.ts @@ -12,7 +12,7 @@ import { NzDrawerRef } from './nz-drawer-ref'; export type NzDrawerPlacement = 'left' | 'right' | 'top' | 'bottom'; // tslint:disable-next-line:no-any -export interface NzDrawerOptions { +export interface NzDrawerOptionsOfComponent { nzClosable?: boolean; nzMaskClosable?: boolean; nzMask?: boolean; @@ -30,3 +30,9 @@ export interface NzDrawerOptions { nzOffsetX?: number; nzOffsetY?: number; } + +// tslint:disable-next-line:no-any +export interface NzDrawerOptions extends NzDrawerOptionsOfComponent { + // tslint:disable-next-line:no-any + nzOnCancel?(): Promise; +} diff --git a/components/drawer/nz-drawer.component.ts b/components/drawer/nz-drawer.component.ts index abb9f5f81d9..c42ca15c4cd 100644 --- a/components/drawer/nz-drawer.component.ts +++ b/components/drawer/nz-drawer.component.ts @@ -36,7 +36,7 @@ import { CdkPortalOutlet, ComponentPortal, PortalInjector, TemplatePortal } from import { Observable, Subject } from 'rxjs'; import { toCssPixel, InputBoolean } from 'ng-zorro-antd/core'; -import { NzDrawerOptions, NzDrawerPlacement } from './nz-drawer-options'; +import { NzDrawerOptionsOfComponent, NzDrawerPlacement } from './nz-drawer-options'; import { NzDrawerRef } from './nz-drawer-ref'; export const DRAWER_ANIMATE_DURATION = 300; @@ -50,7 +50,7 @@ export const DRAWER_ANIMATE_DURATION = 300; }) // tslint:disable-next-line:no-any export class NzDrawerComponent extends NzDrawerRef - implements OnInit, OnDestroy, AfterViewInit, OnChanges, NzDrawerOptions { + implements OnInit, OnDestroy, AfterViewInit, OnChanges, NzDrawerOptionsOfComponent { @Input() nzContent: TemplateRef<{ $implicit: D; drawerRef: NzDrawerRef }> | Type; @Input() @InputBoolean() nzClosable = true; @Input() @InputBoolean() nzMaskClosable = true; diff --git a/components/drawer/nz-drawer.service.ts b/components/drawer/nz-drawer.service.ts index 5aedc74dbde..971ba0cb1b4 100644 --- a/components/drawer/nz-drawer.service.ts +++ b/components/drawer/nz-drawer.service.ts @@ -11,7 +11,7 @@ import { ComponentPortal } from '@angular/cdk/portal'; import { ComponentRef, Injectable } from '@angular/core'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { NzDrawerOptions } from './nz-drawer-options'; +import { NzDrawerOptions, NzDrawerOptionsOfComponent } from './nz-drawer-options'; import { NzDrawerRef } from './nz-drawer-ref'; import { NzDrawerComponent } from './nz-drawer.component'; @@ -21,16 +21,25 @@ export class DrawerBuilderForService { private unsubscribe$ = new Subject(); constructor(private overlay: Overlay, private options: NzDrawerOptions) { + /** pick {@link NzDrawerOptions.nzOnCancel} and omit this option */ + const { nzOnCancel, ...componentOption } = this.options; this.createDrawer(); - this.updateOptions(this.options); + this.updateOptions(componentOption); // Prevent repeatedly open drawer when tap focus element. this.drawerRef!.instance.savePreviouslyFocusedElement(); this.drawerRef!.instance.nzOnViewInit.pipe(takeUntil(this.unsubscribe$)).subscribe(() => { this.drawerRef!.instance.open(); }); - this.drawerRef!.instance.nzOnClose.subscribe(() => { - this.drawerRef!.instance.close(); + if (nzOnCancel) { + nzOnCancel().then(canClose => { + if (canClose !== false) { + this.drawerRef!.instance.close(); + } + }); + } else { + this.drawerRef!.instance.close(); + } }); this.drawerRef!.instance.afterClose.pipe(takeUntil(this.unsubscribe$)).subscribe(() => { @@ -50,7 +59,7 @@ export class DrawerBuilderForService { this.drawerRef = this.overlayRef.attach(new ComponentPortal(NzDrawerComponent)); } - updateOptions(options: NzDrawerOptions): void { + updateOptions(options: NzDrawerOptionsOfComponent): void { Object.assign(this.drawerRef!.instance, options); } } diff --git a/components/drawer/nz-drawer.spec.ts b/components/drawer/nz-drawer.spec.ts index 37c77257de9..6a757f4b640 100644 --- a/components/drawer/nz-drawer.spec.ts +++ b/components/drawer/nz-drawer.spec.ts @@ -385,7 +385,7 @@ describe('NzDrawerService', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [NzDrawerModule], + imports: [NzDrawerModule, NoopAnimationsModule], providers: [NzDrawerService], declarations: [NzTestDrawerWithServiceComponent, NzDrawerCustomComponent] }); @@ -431,7 +431,7 @@ describe('NzDrawerService', () => { nzContentParams: { value: 1 } }); drawerRef.afterOpen.subscribe(openSpy); - drawerRef.afterOpen.subscribe(closeSpy); + drawerRef.afterClose.subscribe(closeSpy); fixture.detectChanges(); expect(openSpy).not.toHaveBeenCalled(); tick(300); @@ -440,6 +440,34 @@ describe('NzDrawerService', () => { fixture.detectChanges(); tick(300); expect(closeSpy).toHaveBeenCalled(); + fixture.detectChanges(); + })); + + it('should `nzOnCancel` work', fakeAsync(() => { + let canClose = false; + const openSpy = jasmine.createSpy('afterOpen spy'); + const closeSpy = jasmine.createSpy('afterClose spy').and.returnValue(1); + const drawerRef = drawerService.create({ + nzTitle: 'Service nzOnCancel', + nzContent: NzDrawerCustomComponent, + nzOnCancel: () => Promise.resolve(canClose) + }); + drawerRef.afterOpen.subscribe(openSpy); + drawerRef.afterClose.subscribe(closeSpy); + fixture.detectChanges(); + expect(openSpy).not.toHaveBeenCalled(); + tick(300); + expect(openSpy).toHaveBeenCalled(); + (overlayContainerElement.querySelector('.ant-drawer .ant-drawer-close') as HTMLElement).click(); + fixture.detectChanges(); + tick(300); + expect(closeSpy).not.toHaveBeenCalled(); + fixture.detectChanges(); + canClose = true; + (overlayContainerElement.querySelector('.ant-drawer .ant-drawer-close') as HTMLElement).click(); + fixture.detectChanges(); + tick(300); + expect(closeSpy).toHaveBeenCalled(); })); });