Skip to content

Commit

Permalink
refactor(module:modal): refactor the component (#4702)
Browse files Browse the repository at this point in the history
* refactor(module:modal): refactor the modal service

close #3652, close #4437, close #2749

* feat(module:modal): support autofocus

close #3423, close #4126

* refactor(module:modal): refactor the modal component

* chore: rename files

* test(module:modal): add test case

* test(module:modal): add test case

* feat(module:modal): support nzCloseOnNavigation

* feat(module:modal): support nzViewContainerRef

close #4710

test(module:modal): add footer directive test

test(module:modal): add callback test

test(module:modal): add animation test

test(module:modal): add classname and styles test

test(module:modal): add footer component test

test(module:modal): fix test

test(module:modal): fix test

test(module:modal): add confirm test

test(module:modal): fix test

test(module:modal): add component mode test

chore: remove console

test: fix ci test
  • Loading branch information
hsuanxyz authored Mar 15, 2020
1 parent a5eda6f commit b3d3885
Show file tree
Hide file tree
Showing 36 changed files with 3,259 additions and 2,329 deletions.
1 change: 1 addition & 0 deletions components/modal/demo/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Component } from '@angular/core';
<p>Content one</p>
<p>Content two</p>
<p>Content three</p>
<p>Content three</p>
</nz-modal>
`
})
Expand Down
6 changes: 3 additions & 3 deletions components/modal/demo/confirm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ import { NzModalService } from 'ng-zorro-antd/modal';
]
})
export class NzDemoModalConfirmComponent {
constructor(private modalService: NzModalService) {}
constructor(private modal: NzModalService) {}

showConfirm(): void {
this.modalService.confirm({
this.modal.confirm({
nzTitle: '<i>Do you Want to delete these items?</i>',
nzContent: '<b>Some descriptions</b>',
nzOnOk: () => console.log('OK')
});
}

showDeleteConfirm(): void {
this.modalService.confirm({
this.modal.confirm({
nzTitle: 'Are you sure delete this task?',
nzContent: '<b style="color: red;">Some descriptions</b>',
nzOkText: 'Yes',
Expand Down
10 changes: 5 additions & 5 deletions components/modal/demo/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,32 @@ import { NzModalService } from 'ng-zorro-antd/modal';
]
})
export class NzDemoModalInfoComponent {
constructor(private modalService: NzModalService) {}
constructor(private modal: NzModalService) {}

info(): void {
this.modalService.info({
this.modal.info({
nzTitle: 'This is a notification message',
nzContent: '<p>some messages...some messages...</p><p>some messages...some messages...</p>',
nzOnOk: () => console.log('Info OK')
});
}

success(): void {
this.modalService.success({
this.modal.success({
nzTitle: 'This is a success message',
nzContent: 'some messages...some messages...'
});
}

error(): void {
this.modalService.error({
this.modal.error({
nzTitle: 'This is an error message',
nzContent: 'some messages...some messages...'
});
}

warning(): void {
this.modalService.warning({
this.modal.warning({
nzTitle: 'This is an warning message',
nzContent: 'some messages...some messages...'
});
Expand Down
26 changes: 13 additions & 13 deletions components/modal/demo/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ export class NzDemoModalServiceComponent {
htmlModalVisible = false;
disabled = false;

constructor(private modalService: NzModalService) {}
constructor(private modal: NzModalService) {}

createModal(): void {
this.modalService.create({
this.modal.create({
nzTitle: 'Modal Title',
nzContent: 'string, will close after 1 sec',
nzClosable: false,
Expand All @@ -70,7 +70,7 @@ export class NzDemoModalServiceComponent {
}

createTplModal(tplTitle: TemplateRef<{}>, tplContent: TemplateRef<{}>, tplFooter: TemplateRef<{}>): void {
this.tplModal = this.modalService.create({
this.tplModal = this.modal.create({
nzTitle: tplTitle,
nzContent: tplContent,
nzFooter: tplFooter,
Expand All @@ -89,13 +89,15 @@ export class NzDemoModalServiceComponent {
}

createComponentModal(): void {
const modal = this.modalService.create({
const modal = this.modal.create({
nzTitle: 'Modal Title',
nzContent: NzModalCustomComponent,
nzGetContainer: () => document.body,
nzComponentParams: {
title: 'title in component',
subtitle: 'component sub title,will be changed after 2 sec'
},
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000)),
nzFooter: [
{
label: 'change component title from outside',
Expand All @@ -105,33 +107,31 @@ export class NzDemoModalServiceComponent {
}
]
});

const instance = modal.getContentComponent();
modal.afterOpen.subscribe(() => console.log('[afterOpen] emitted!'));

// Return a result when closed
modal.afterClose.subscribe(result => console.log('[afterClose] The result is:', result));

// delay until modal instance created
setTimeout(() => {
const instance = modal.getContentComponent();
instance.subtitle = 'sub title is changed';
}, 2000);
}

createCustomButtonModal(): void {
const modal: NzModalRef = this.modalService.create({
const modal: NzModalRef = this.modal.create({
nzTitle: 'custom button demo',
nzContent: 'pass array of button config to nzFooter to create multiple buttons',
nzFooter: [
{
label: 'Close',
shape: 'default',
shape: 'round',
onClick: () => modal.destroy()
},
{
label: 'Confirm',
type: 'primary',
onClick: () => this.modalService.confirm({ nzTitle: 'Confirm Modal Title', nzContent: 'Confirm Modal Content' })
onClick: () => this.modal.confirm({ nzTitle: 'Confirm Modal Title', nzContent: 'Confirm Modal Content' })
},
{
label: 'Change Button Status',
Expand Down Expand Up @@ -161,7 +161,7 @@ export class NzDemoModalServiceComponent {

['create', 'info', 'success', 'error'].forEach(method =>
// @ts-ignore
this.modalService[method]({
this.modal[method]({
nzMask: false,
nzTitle: `Test ${method} title`,
nzContent: `Test content: <b>${method}</b>`,
Expand All @@ -171,9 +171,9 @@ export class NzDemoModalServiceComponent {

this.htmlModalVisible = true;

this.modalService.afterAllClose.subscribe(() => console.log('afterAllClose emitted!'));
this.modal.afterAllClose.subscribe(() => console.log('afterAllClose emitted!'));

setTimeout(() => this.modalService.closeAll(), 2000);
setTimeout(() => this.modal.closeAll(), 2000);
}
}

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 @@ -58,6 +58,7 @@ The dialog is currently divided into 2 modes, `normal mode` and `confirm box mod
| nzContent | Content | string / TemplateRef / Component / ng-content | - |
| nzComponentParams | When nzContent is a Component, the attributes in this parameter will be passed to the nzContent instance | `object` | - |
| nzIconType | Icon type of the Icon component. <i>Only valid in confirm box mode</i> | `string` | question-circle |
| nzAutofocus | autofocus and the position,disabled when is `null` | `'ok' \| 'cancel' \| 'auto' \| null` | `'auto'` |

#### Attentions

Expand Down
4 changes: 3 additions & 1 deletion components/modal/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ import { NzModalModule } from 'ng-zorro-antd/modal';
| nzOnOk | 点击确定回调(若nzContent为Component,则将会以该Component实例作为参数)。<i>注:当以`NzModalService.create`创建时,此参数应传入function(回调函数)。该函数可返回promise,待执行完毕或promise结束时,将自动关闭对话框(返回false可阻止关闭)</i> | EventEmitter | - |
| nzContent | 内容 | string<br>TemplateRef<br>Component<br>ng-content | - |
| nzComponentParams | 当nzContent为组件类(Component)时,该参数中的属性将传入nzContent实例中 | `object` | - |
| nzIconType | 图标 Icon 类型。<i>仅 确认框模式 下有效</i> | `string` | question-circle |
| nzIconType | 图标 Icon 类型。<i>仅 确认框模式 下有效</i> | `string` | `'question-circle'` |
| nzAutofocus | 自动聚焦及聚焦位置,为 `null` 时禁用 | `'ok' \| 'cancel' \| 'auto' \| null` | `'auto'` |


#### 注意

Expand Down
20 changes: 20 additions & 0 deletions components/modal/modal-animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @license
* Copyright Alibaba.com All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { animate, AnimationTriggerMetadata, state, style, transition, trigger } from '@angular/animations';

export const nzModalAnimations: {
readonly modalContainer: AnimationTriggerMetadata;
} = {
modalContainer: trigger('modalContainer', [
state('void, exit', style({})),
state('enter', style({})),
transition('* => enter', animate('.24s', style({}))),
transition('* => void, * => exit', animate('.2s', style({})))
])
};
31 changes: 31 additions & 0 deletions components/modal/modal-close.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @license
* Copyright Alibaba.com All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ModalOptions } from './modal-types';

@Component({
selector: 'button[nz-modal-close]',
exportAs: 'NzModalCloseBuiltin',
template: `
<span class="ant-modal-close-x">
<ng-container *nzStringTemplateOutlet="config?.nzCloseIcon">
<i nz-icon [nzType]="config?.nzCloseIcon" class="ant-modal-close-icon"></i>
</ng-container>
</span>
`,
host: {
class: 'ant-modal-close',
'aria-label': 'Close'
},
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NzModalCloseComponent {
constructor(public config: ModalOptions) {}
}
File renamed without changes.
154 changes: 154 additions & 0 deletions components/modal/modal-confirm-container.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* @license
* Copyright Alibaba.com All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { FocusTrapFactory } from '@angular/cdk/a11y';
import { OverlayRef } from '@angular/cdk/overlay';
import { CdkPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
import { DOCUMENT } from '@angular/common';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Inject,
NgZone,
OnDestroy,
Optional,
Output,
Renderer2,
ViewChild
} from '@angular/core';
import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';

import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { NzI18nService } from 'ng-zorro-antd/i18n';

import { nzModalAnimations } from './modal-animations';
import { BaseModalContainer } from './modal-container';
import { ModalOptions } from './modal-types';

@Component({
selector: 'nz-modal-confirm-container',
exportAs: 'nzModalConfirmContainer',
template: `
<div
#modalElement
role="document"
class="ant-modal"
[class]="config.nzClassName"
[ngStyle]="config.nzStyle"
[style.width]="config?.nzWidth | nzToCssUnit"
>
<div class="ant-modal-content">
<button *ngIf="config.nzClosable" nz-modal-close (click)="onCloseClick()"></button>
<div class="ant-modal-body" [ngStyle]="config.nzBodyStyle">
<div class="ant-modal-confirm-body-wrapper">
<div class="ant-modal-confirm-body">
<i nz-icon [nzType]="config.nzIconType"></i>
<span class="ant-modal-confirm-title">
<ng-container *nzStringTemplateOutlet="config.nzTitle">
<span [innerHTML]="config.nzTitle"></span>
</ng-container>
</span>
<div class="ant-modal-confirm-content">
<ng-template cdkPortalOutlet></ng-template>
<div *ngIf="isStringContent" [innerHTML]="config.nzContent"></div>
</div>
</div>
<div class="ant-modal-confirm-btns">
<button
*ngIf="config.nzCancelText !== null"
[attr.cdkFocusInitial]="config.nzAutofocus === 'cancel'"
nz-button
(click)="onCancel()"
[nzLoading]="config.nzCancelLoading"
[disabled]="config.nzCancelDisabled"
>
{{ config.nzCancelText || locale.cancelText }}
</button>
<button
*ngIf="config.nzOkText !== null"
[attr.cdkFocusInitial]="config.nzAutofocus === 'ok'"
nz-button
[nzType]="config.nzOkType"
(click)="onOk()"
[nzLoading]="config.nzOkLoading"
[disabled]="config.nzOkDisabled"
>
{{ config.nzOkText || locale.okText }}
</button>
</div>
</div>
</div>
</div>
</div>
`,
animations: [nzModalAnimations.modalContainer],
// Using OnPush for modal caused footer can not to detect changes. we can fix it when 8.x.
changeDetection: ChangeDetectionStrategy.Default,
host: {
tabindex: '-1',
role: 'dialog',
class: 'ant-modal-wrap',
'[class]': 'config.nzWrapClassName',
'[style.zIndex]': 'config.nzZIndex',
'[@.disabled]': 'config.nzNoAnimation',
'[@modalContainer]': 'state',
'(@modalContainer.start)': 'onAnimationStart($event)',
'(@modalContainer.done)': 'onAnimationDone($event)',
'(mousedown)': 'onMousedown($event)',
'(mouseup)': 'onMouseup($event)'
}
})
export class NzModalConfirmContainerComponent extends BaseModalContainer implements OnDestroy {
@ViewChild(CdkPortalOutlet, { static: true }) portalOutlet: CdkPortalOutlet;
@ViewChild('modalElement', { static: true }) modalElementRef: ElementRef<HTMLDivElement>;
@Output() readonly cancelTriggered = new EventEmitter<void>();
@Output() readonly okTriggered = new EventEmitter<void>();
locale: { okText?: string; cancelText?: string } = {};
private destroy$ = new Subject<void>();

constructor(
private i18n: NzI18nService,
elementRef: ElementRef,
focusTrapFactory: FocusTrapFactory,
cdr: ChangeDetectorRef,
render: Renderer2,
zone: NgZone,
overlayRef: OverlayRef,
public config: ModalOptions,
// tslint:disable-next-line:no-any
@Optional() @Inject(DOCUMENT) document: any,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string
) {
super(elementRef, focusTrapFactory, cdr, render, zone, overlayRef, config, document, animationType);
this.i18n.localeChange.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.locale = this.i18n.getLocaleData('Modal');
});
}

onCancel(): void {
this.cancelTriggered.emit();
}

onOk(): void {
this.okTriggered.emit();
}

attachComponentPortal<T>(_portal: ComponentPortal<T>): never {
throw new Error('The confirm mode does not support using component as content');
}

ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}
Loading

0 comments on commit b3d3885

Please sign in to comment.