Skip to content

Commit

Permalink
fix(module:modal): modal cannot close after the host view destroyed
Browse files Browse the repository at this point in the history
close #5128, close #5161
  • Loading branch information
hsuanxyz committed Apr 27, 2020
1 parent 18e7913 commit 55bb6b0
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 13 deletions.
1 change: 1 addition & 0 deletions components/core/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ export interface MessageConfig {
export interface ModalConfig {
nzMask?: boolean;
nzMaskClosable?: boolean;
nzCloseOnNavigation?: boolean;
}

export interface NotificationConfig extends MessageConfig {
Expand Down
1 change: 1 addition & 0 deletions components/modal/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ The dialog is currently divided into 2 modes, `normal mode` and `confirm box mod
| nzKeyboard | Whether support press esc to close | `boolean` | `true` |
| nzMask | Whether show mask or not. | `boolean` | `true` ||
| nzMaskClosable | Whether to close the modal dialog when the mask (area outside the modal) is clicked | `boolean` | `true` ||
| nzCloseOnNavigation | Whether to close the modal when the navigation history changes | `boolean` | `true` ||
| nzMaskStyle | Style for modal's mask element. | `object` | - |
| nzOkText | Text of the OK button. <i>Set to null to show no ok button (this value is invalid if the nzFooter parameter is used in normal mode)</i> | `string` | OK |
| nzOkType | Button type of the OK button. <i>Consistent with the type of the `nz-button`.</i> | `string` | primary |
Expand Down
1 change: 1 addition & 0 deletions components/modal/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { NzModalModule } from 'ng-zorro-antd/modal';
| nzKeyboard | 是否支持键盘esc关闭 | `boolean` | `true` |
| nzMask | 是否展示遮罩 | `boolean` | `true` ||
| nzMaskClosable | 点击蒙层是否允许关闭 | `boolean` | `true` ||
| nzCloseOnNavigation | 导航历史变化时是否关闭模态框 | `boolean` | `true` ||
| nzMaskStyle | 遮罩样式 | `object` | - |
| nzOkText | 确认按钮文字。<i>设为 null 表示不显示确认按钮(若在普通模式下使用了 nzFooter 参数,则该值无效)</i> | `string` | 确定 |
| nzOkType | 确认按钮类型。<i>与button的type类型值一致</i> | `string` | primary |
Expand Down
9 changes: 7 additions & 2 deletions components/modal/modal-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AnimationEvent } from '@angular/animations';
import { FocusTrap, FocusTrapFactory } from '@angular/cdk/a11y';
import { OverlayRef } from '@angular/cdk/overlay';
import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, TemplatePortal } from '@angular/cdk/portal';
import { ChangeDetectorRef, ComponentRef, ElementRef, EmbeddedViewRef, EventEmitter, NgZone, Renderer2 } from '@angular/core';
import { ChangeDetectorRef, ComponentRef, ElementRef, EmbeddedViewRef, EventEmitter, NgZone, OnDestroy, Renderer2 } from '@angular/core';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { getElementOffset } from 'ng-zorro-antd/core/util';
import { FADE_CLASS_NAME_MAP, MODAL_MASK_CLASS_NAME, ZOOM_CLASS_NAME_MAP } from './modal-config';
Expand All @@ -22,14 +22,15 @@ export function throwNzModalContentAlreadyAttachedError(): never {
throw Error('Attempting to attach modal content after content is already attached');
}

export class BaseModalContainer extends BasePortalOutlet {
export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {
portalOutlet: CdkPortalOutlet;
modalElementRef: ElementRef<HTMLDivElement>;

animationStateChanged = new EventEmitter<AnimationEvent>();
containerClick = new EventEmitter<void>();
cancelTriggered = new EventEmitter<void>();
okTriggered = new EventEmitter<void>();
onDestroy = new EventEmitter<void>();

state: 'void' | 'enter' | 'exit' = 'enter';
document: Document;
Expand Down Expand Up @@ -57,6 +58,10 @@ export class BaseModalContainer extends BasePortalOutlet {
this.setContainer();
}

ngOnDestroy(): void {
this.onDestroy.emit();
}

onMousedown(e: MouseEvent): void {
this.latestMousedownTarget = (e.target as HTMLElement) || null;
}
Expand Down
19 changes: 13 additions & 6 deletions components/modal/modal-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { OverlayRef } from '@angular/cdk/overlay';
import { EventEmitter } from '@angular/core';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { isPromise } from 'ng-zorro-antd/core/util';
import { Subject } from 'rxjs';
import { merge, Subject } from 'rxjs';
import { filter, take } from 'rxjs/operators';

import { BaseModalContainer } from './modal-container';
Expand Down Expand Up @@ -51,14 +51,17 @@ export class NzModalRef<T = NzSafeAny, R = NzSafeAny> implements NzModalLegacyAP
}
});

containerInstance.animationStateChanged
.pipe(
merge(
containerInstance.onDestroy,
containerInstance.animationStateChanged.pipe(
filter(event => event.phaseName === 'done' && event.toState === 'exit'),
take(1)
)
)
.pipe(take(1))
.subscribe(() => {
clearTimeout(this.closeTimeout);
this.overlayRef.dispose();
this.finishDialogClose();
});

containerInstance.containerClick.pipe(take(1)).subscribe(() => {
Expand Down Expand Up @@ -138,10 +141,9 @@ export class NzModalRef<T = NzSafeAny, R = NzSafeAny> implements NzModalLegacyAP
take(1)
)
.subscribe(event => {
this.state = NzModalState.CLOSED;
this.overlayRef.detachBackdrop();
this.closeTimeout = setTimeout(() => {
this.overlayRef.dispose();
this.finishDialogClose();
}, event.totalTime + 100);
});

Expand Down Expand Up @@ -196,4 +198,9 @@ export class NzModalRef<T = NzSafeAny, R = NzSafeAny> implements NzModalLegacyAP
this.close(result);
}
}

private finishDialogClose(): void {
this.state = NzModalState.CLOSED;
this.overlayRef.dispose();
}
}
2 changes: 2 additions & 0 deletions components/modal/modal.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const NZ_CONFIG_COMPONENT_NAME = 'modal';
export class NzModalComponent<T = NzSafeAny, R = NzSafeAny> implements OnChanges, NzModalLegacyAPI<T, R> {
static ngAcceptInputType_nzMask: BooleanInput;
static ngAcceptInputType_nzMaskClosable: BooleanInput;
static ngAcceptInputType_nzCloseOnNavigation: BooleanInput;
static ngAcceptInputType_nzVisible: BooleanInput;
static ngAcceptInputType_nzClosable: BooleanInput;
static ngAcceptInputType_nzOkLoading: BooleanInput;
Expand All @@ -58,6 +59,7 @@ export class NzModalComponent<T = NzSafeAny, R = NzSafeAny> implements OnChanges

@Input() @WithConfig(NZ_CONFIG_COMPONENT_NAME, true) @InputBoolean() nzMask: boolean;
@Input() @WithConfig(NZ_CONFIG_COMPONENT_NAME, true) @InputBoolean() nzMaskClosable: boolean;
@Input() @WithConfig(NZ_CONFIG_COMPONENT_NAME, true) @InputBoolean() nzCloseOnNavigation: boolean;
@Input() @InputBoolean() nzVisible: boolean = false;
@Input() @InputBoolean() nzClosable: boolean = true;
@Input() @InputBoolean() nzOkLoading: boolean = false;
Expand Down
18 changes: 15 additions & 3 deletions components/modal/modal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,20 @@ describe('NzModal', () => {
modalInstance.triggerCancel();
}).not.toThrowError();
}));

it('should close when the host view is destroyed', fakeAsync(() => {
componentInstance.isVisible = true;
componentFixture.detectChanges();
flush();

expect(overlayContainerElement.querySelector('nz-modal-container')).not.toBeNull();

componentFixture.destroy();
componentFixture.detectChanges();
flush();

expect(overlayContainerElement.querySelector('nz-modal-container')).toBeNull();
}));
});
});

Expand All @@ -1383,9 +1397,7 @@ class TestWithViewContainerDirective {
}

@Component({
template: `
<test-with-view-container></test-with-view-container>
`
template: ` <test-with-view-container></test-with-view-container> `
})
class TestWithChildViewContainerComponent {
@ViewChild(TestWithViewContainerDirective) childWithViewContainer: TestWithViewContainerDirective;
Expand Down
6 changes: 4 additions & 2 deletions components/modal/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export function getConfigFromComponent(component: NzModalComponent): ModalOption
nzOnOk,
nzOnCancel,
nzAfterOpen,
nzAfterClose
nzAfterClose,
nzCloseOnNavigation
} = component;
return {
nzMask,
Expand Down Expand Up @@ -87,6 +88,7 @@ export function getConfigFromComponent(component: NzModalComponent): ModalOption
nzOnOk,
nzOnCancel,
nzAfterOpen,
nzAfterClose
nzAfterClose,
nzCloseOnNavigation
};
}

0 comments on commit 55bb6b0

Please sign in to comment.