Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(module:modal): modal cannot close after the host view destroyed #5161

Merged
merged 1 commit into from
May 11, 2020
Merged
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
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) @InputBoolean() nzMask: boolean = true;
@Input() @WithConfig(NZ_CONFIG_COMPONENT_NAME) @InputBoolean() nzMaskClosable: boolean = true;
@Input() @WithConfig(NZ_CONFIG_COMPONENT_NAME) @InputBoolean() nzCloseOnNavigation: boolean = true;
@Input() @InputBoolean() nzVisible: boolean = false;
@Input() @InputBoolean() nzClosable: boolean = true;
@Input() @InputBoolean() nzOkLoading: boolean = false;
Expand Down
14 changes: 14 additions & 0 deletions components/modal/modal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,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 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
};
}