Skip to content

Commit

Permalink
fix(module:modal): some cases there is no changes detected (#5332)
Browse files Browse the repository at this point in the history
* fix(module:modal): some cases there is no changes detected

close #5328, close #5287, close #5259

* docs(module:modal): update the API docs

close #3743
  • Loading branch information
hsuanxyz committed Jun 16, 2020
1 parent 182e790 commit ade6198
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 88 deletions.
5 changes: 3 additions & 2 deletions components/modal/demo/service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* declarations: NzModalCustomComponent */

import { Component, Input, TemplateRef } from '@angular/core';
import { Component, Input, TemplateRef, ViewContainerRef } from '@angular/core';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';

@Component({
Expand Down Expand Up @@ -57,7 +57,7 @@ export class NzDemoModalServiceComponent {
htmlModalVisible = false;
disabled = false;

constructor(private modal: NzModalService) {}
constructor(private modal: NzModalService, private viewContainerRef: ViewContainerRef) {}

createModal(): void {
this.modal.create({
Expand Down Expand Up @@ -94,6 +94,7 @@ export class NzDemoModalServiceComponent {
const modal = this.modal.create({
nzTitle: 'Modal Title',
nzContent: NzModalCustomComponent,
nzViewContainerRef: this.viewContainerRef,
nzGetContainer: () => document.body,
nzComponentParams: {
title: 'title in component',
Expand Down
2 changes: 1 addition & 1 deletion components/modal/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ The dialog created by the service method `NzModalService.xxx()` will return a `N
|----|----|
| afterOpen | Same as nzAfterOpen but of type Observable<void> |
| afterClose | Same as nzAfterClose, but of type Observable<result:any> |
| open() | Open (display) dialog box. <i>Calling this function will fail if the dialog is already destroyed</i> |
| close() | Close (hide) the dialog. <i>Note: When used for a dialog created as a service, this method will destroy the dialog directly (as with the destroy method)</i> |
| destroy() | Destroy the dialog. <i>Note: Used only for dialogs created by the service (non-service created dialogs, this method only hides the dialog)</i> |
| getContentComponent() | Gets the Component instance in the contents of the dialog for `nzContent`. <i> Note: When the dialog is not initialized (`ngOnInit` is not executed), this function will return `undefined`</i> |
| triggerOk() | Manually trigger nzOnOk |
| triggerCancel() | Manually trigger nzOnCancel |
| updateConfig(config: ModalOptions): void | Update the config |

### ModalButtonOptions (used to customize the bottom button)

Expand Down
2 changes: 1 addition & 1 deletion components/modal/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ constructor(modal: NzModalService) {
|----|----|
| afterOpen | 同nzAfterOpen,但类型为Observable&lt;void&gt; |
| afterClose | 同nzAfterClose,但类型为Observable&lt;result:any&gt; |
| open() | 打开(显示)对话框。<i>若对话框已销毁,则调用此函数将失效</i> |
| close(result: any) | 关闭(隐藏)对话框。<i>注:当用于以服务方式创建的对话框,此方法将直接 销毁 对话框(同destroy方法)</i> |
| destroy(result: any) | 销毁对话框。<i>注:仅用于服务方式创建的对话框(非服务方式创建的对话框,此方法只会隐藏对话框)</i> |
| getContentComponent() | 获取对话框内容中`nzContent`的Component实例instance。<i>注:当对话框还未初始化完毕(`ngOnInit`未执行)时,此函数将返回`undefined`</i> |
| triggerOk() | 手动触发nzOnOk |
| triggerCancel() | 手动触发nzOnCancel |
| updateConfig(config: ModalOptions): void | 更新配置 |

### ModalButtonOptions(用于自定义底部按钮)

Expand Down
8 changes: 3 additions & 5 deletions components/modal/modal-confirm-container.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { FocusTrapFactory } from '@angular/cdk/a11y';
import { ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';
import { OverlayRef } from '@angular/cdk/overlay';
import { CdkPortalOutlet } from '@angular/cdk/portal';
import { DOCUMENT } from '@angular/common';
Expand All @@ -14,7 +14,6 @@ import {
ElementRef,
EventEmitter,
Inject,
NgZone,
Optional,
Output,
Renderer2,
Expand Down Expand Up @@ -115,17 +114,16 @@ export class NzModalConfirmContainerComponent extends BaseModalContainer {
constructor(
private i18n: NzI18nService,
elementRef: ElementRef,
focusTrapFactory: FocusTrapFactory,
focusTrapFactory: ConfigurableFocusTrapFactory,
cdr: ChangeDetectorRef,
render: Renderer2,
zone: NgZone,
overlayRef: OverlayRef,
nzConfigService: NzConfigService,
public config: ModalOptions,
@Optional() @Inject(DOCUMENT) document: NzSafeAny,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string
) {
super(elementRef, focusTrapFactory, cdr, render, zone, overlayRef, nzConfigService, config, document, animationType);
super(elementRef, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);
this.i18n.localeChange.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.locale = this.i18n.getLocaleData('Modal');
});
Expand Down
19 changes: 4 additions & 15 deletions components/modal/modal-container.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,11 @@
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { FocusTrapFactory } from '@angular/cdk/a11y';
import { ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';
import { OverlayRef } from '@angular/cdk/overlay';
import { CdkPortalOutlet } from '@angular/cdk/portal';
import { DOCUMENT } from '@angular/common';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
Inject,
NgZone,
Optional,
Renderer2,
ViewChild
} from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inject, Optional, Renderer2, ViewChild } from '@angular/core';
import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
import { NzConfigService } from 'ng-zorro-antd/core/config';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
Expand Down Expand Up @@ -77,16 +67,15 @@ export class NzModalContainerComponent extends BaseModalContainer {
@ViewChild('modalElement', { static: true }) modalElementRef!: ElementRef<HTMLDivElement>;
constructor(
elementRef: ElementRef,
focusTrapFactory: FocusTrapFactory,
focusTrapFactory: ConfigurableFocusTrapFactory,
cdr: ChangeDetectorRef,
render: Renderer2,
zone: NgZone,
overlayRef: OverlayRef,
nzConfigService: NzConfigService,
public config: ModalOptions,
@Optional() @Inject(DOCUMENT) document: NzSafeAny,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string
) {
super(elementRef, focusTrapFactory, cdr, render, zone, overlayRef, nzConfigService, config, document, animationType);
super(elementRef, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);
}
}
106 changes: 53 additions & 53 deletions components/modal/modal-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
*/

import { AnimationEvent } from '@angular/animations';
import { FocusTrap, FocusTrapFactory } from '@angular/cdk/a11y';
import { ConfigurableFocusTrapFactory, FocusTrap } 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, OnDestroy, Renderer2 } from '@angular/core';
import { ChangeDetectorRef, ComponentRef, ElementRef, EmbeddedViewRef, EventEmitter, OnDestroy, Renderer2 } from '@angular/core';
import { NzConfigService } from 'ng-zorro-antd/core/config';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { getElementOffset } from 'ng-zorro-antd/core/util';
Expand All @@ -31,7 +31,6 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {
containerClick = new EventEmitter<void>();
cancelTriggered = new EventEmitter<void>();
okTriggered = new EventEmitter<void>();
onDestroy = new EventEmitter<void>();

state: 'void' | 'enter' | 'exit' = 'enter';
document: Document;
Expand All @@ -57,10 +56,9 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {

constructor(
protected elementRef: ElementRef,
protected focusTrapFactory: FocusTrapFactory,
protected focusTrapFactory: ConfigurableFocusTrapFactory,
public cdr: ChangeDetectorRef,
protected render: Renderer2,
protected zone: NgZone,
protected overlayRef: OverlayRef,
protected nzConfigService: NzConfigService,
public config: ModalOptions,
Expand Down Expand Up @@ -143,6 +141,10 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {
}

private savePreviouslyFocusedElement(): void {
if (!this.focusTrap) {
this.focusTrap = this.focusTrapFactory.create(this.elementRef.nativeElement);
}

if (this.document) {
this.elementFocusedBeforeModalWasOpened = this.document.activeElement as HTMLElement;
if (this.elementRef.nativeElement.focus) {
Expand All @@ -154,10 +156,6 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {
private trapFocus(): void {
const element = this.elementRef.nativeElement;

if (!this.focusTrap) {
this.focusTrap = this.focusTrapFactory.create(element);
}

if (this.config.nzAutofocus) {
this.focusTrap.focusInitialElementWhenReady().then();
} else {
Expand Down Expand Up @@ -190,56 +188,60 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {
if (this.animationDisabled()) {
return;
}
this.zone.runOutsideAngular(() => {
// Make sure to set the `TransformOrigin` style before set the modelElement's class names
this.setModalTransformOrigin();
const modalElement = this.modalElementRef.nativeElement;
const backdropElement = this.overlayRef.backdropElement;
this.render.addClass(modalElement, ZOOM_CLASS_NAME_MAP.enter);
this.render.addClass(modalElement, ZOOM_CLASS_NAME_MAP.enterActive);
this.render.addClass(backdropElement, FADE_CLASS_NAME_MAP.enter);
this.render.addClass(backdropElement, FADE_CLASS_NAME_MAP.enterActive);
});
// Make sure to set the `TransformOrigin` style before set the modelElement's class names
this.setModalTransformOrigin();
const modalElement = this.modalElementRef.nativeElement;
const backdropElement = this.overlayRef.backdropElement;
modalElement.classList.add(ZOOM_CLASS_NAME_MAP.enter);
modalElement.classList.add(ZOOM_CLASS_NAME_MAP.enterActive);
if (backdropElement) {
backdropElement.classList.add(FADE_CLASS_NAME_MAP.enter);
backdropElement.classList.add(FADE_CLASS_NAME_MAP.enterActive);
}
}

private setExitAnimationClass(): void {
this.zone.runOutsideAngular(() => {
const modalElement = this.modalElementRef.nativeElement;
const backdropElement = this.overlayRef.backdropElement;
const modalElement = this.modalElementRef.nativeElement;

modalElement.classList.add(ZOOM_CLASS_NAME_MAP.leave);
modalElement.classList.add(ZOOM_CLASS_NAME_MAP.leaveActive);

this.setMaskExitAnimationClass();
}

if (this.animationDisabled()) {
private setMaskExitAnimationClass(force: boolean = false): void {
const backdropElement = this.overlayRef.backdropElement;
if (backdropElement) {
if (this.animationDisabled() || force) {
// https://github.com/angular/components/issues/18645
this.render.removeClass(backdropElement, MODAL_MASK_CLASS_NAME);
backdropElement.classList.remove(MODAL_MASK_CLASS_NAME);
return;
}

this.render.addClass(modalElement, ZOOM_CLASS_NAME_MAP.leave);
this.render.addClass(modalElement, ZOOM_CLASS_NAME_MAP.leaveActive);
this.render.addClass(backdropElement, FADE_CLASS_NAME_MAP.leave);
this.render.addClass(backdropElement, FADE_CLASS_NAME_MAP.leaveActive);
});
backdropElement.classList.add(FADE_CLASS_NAME_MAP.leave);
backdropElement.classList.add(FADE_CLASS_NAME_MAP.leaveActive);
}
}

private cleanAnimationClass(): void {
if (this.animationDisabled()) {
return;
}
this.zone.runOutsideAngular(() => {
const backdropElement = this.overlayRef.backdropElement;
const modalElement = this.modalElementRef.nativeElement;
this.render.removeClass(modalElement, ZOOM_CLASS_NAME_MAP.enter);
this.render.removeClass(modalElement, ZOOM_CLASS_NAME_MAP.enterActive);
this.render.removeClass(modalElement, ZOOM_CLASS_NAME_MAP.leave);
this.render.removeClass(modalElement, ZOOM_CLASS_NAME_MAP.leaveActive);
this.render.removeClass(backdropElement, FADE_CLASS_NAME_MAP.enter);
this.render.removeClass(backdropElement, FADE_CLASS_NAME_MAP.enterActive);
});
const backdropElement = this.overlayRef.backdropElement;
const modalElement = this.modalElementRef.nativeElement;
if (backdropElement) {
backdropElement.classList.remove(FADE_CLASS_NAME_MAP.enter);
backdropElement.classList.remove(FADE_CLASS_NAME_MAP.enterActive);
}
modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.enter);
modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.enterActive);
modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.leave);
modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.leaveActive);
}

private bindBackdropStyle(): void {
this.zone.runOutsideAngular(() => {
bindBackdropStyle(): void {
const backdropElement = this.overlayRef.backdropElement;
if (backdropElement) {
if (this.oldMaskStyle) {
const backdropElement = this.overlayRef.backdropElement;
const styles = this.oldMaskStyle as { [key: string]: string };
Object.keys(styles).forEach(key => {
this.render.removeStyle(backdropElement, key);
Expand All @@ -248,14 +250,13 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {
}

if (typeof this.config.nzMaskStyle === 'object' && Object.keys(this.config.nzMaskStyle).length) {
const backdropElement = this.overlayRef.backdropElement;
const styles: { [key: string]: string } = { ...this.config.nzMaskStyle };
Object.keys(styles).forEach(key => {
this.render.setStyle(backdropElement, key, styles[key]);
});
this.oldMaskStyle = styles;
}
});
}
}

/**
Expand Down Expand Up @@ -290,17 +291,16 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {

updateMaskClassname(): void {
const backdropElement = this.overlayRef.backdropElement;
if (this.showMask) {
this.render.addClass(backdropElement, MODAL_MASK_CLASS_NAME);
} else {
this.render.removeClass(backdropElement, MODAL_MASK_CLASS_NAME);
if (backdropElement) {
if (this.showMask) {
backdropElement.classList.add(MODAL_MASK_CLASS_NAME);
} else {
backdropElement.classList.remove(MODAL_MASK_CLASS_NAME);
}
}
}

onAnimationDone(event: AnimationEvent): void {
if (event.toState === 'void') {
return;
}
if (event.toState === 'enter') {
this.setContainer();
this.trapFocus();
Expand Down Expand Up @@ -328,7 +328,7 @@ export class BaseModalContainer extends BasePortalOutlet implements OnDestroy {
}

ngOnDestroy(): void {
this.onDestroy.emit();
this.setMaskExitAnimationClass(true);
this.destroy$.next();
this.destroy$.complete();
}
Expand Down
16 changes: 7 additions & 9 deletions components/modal/modal-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,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 { merge, Subject } from 'rxjs';
import { Subject } from 'rxjs';
import { filter, take } from 'rxjs/operators';

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

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

containerInstance.containerClick.pipe(take(1)).subscribe(() => {
Expand Down Expand Up @@ -140,7 +137,7 @@ export class NzModalRef<T = NzSafeAny, R = NzSafeAny> implements NzModalLegacyAP
.subscribe(event => {
this.overlayRef.detachBackdrop();
this.closeTimeout = setTimeout(() => {
this.finishDialogClose();
this._finishDialogClose();
}, event.totalTime + 100);
});

Expand All @@ -150,6 +147,7 @@ export class NzModalRef<T = NzSafeAny, R = NzSafeAny> implements NzModalLegacyAP

updateConfig(config: ModalOptions): void {
Object.assign(this.config, config);
this.containerInstance.bindBackdropStyle();
this.containerInstance.cdr.markForCheck();
}

Expand Down Expand Up @@ -196,7 +194,7 @@ export class NzModalRef<T = NzSafeAny, R = NzSafeAny> implements NzModalLegacyAP
}
}

private finishDialogClose(): void {
_finishDialogClose(): void {
this.state = NzModalState.CLOSED;
this.overlayRef.dispose();
}
Expand Down

0 comments on commit ade6198

Please sign in to comment.