Skip to content

Commit

Permalink
feat(module: modal): support nzMask and nzMaskClosable global con…
Browse files Browse the repository at this point in the history
…fig (NG-ZORRO#3033)
  • Loading branch information
kekehaoz authored and andrew-yangy committed Jun 20, 2019
1 parent 3a55222 commit b575d91
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 25 deletions.
24 changes: 24 additions & 0 deletions components/modal/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,30 @@ The dialog created by the service method `NzModalService.xxx()` will return a `N
| triggerOk() | Manually trigger nzOnOk |
| triggerCancel() | Manually trigger nzOnCancel |


### Global Configuration

Global Configuration(NZ_MODAL_CONFIG)

if your want to set global configuration, you can use the value of provide `NZ_MODAL_CONFIG` to accomplish it.
(eg, add `{ provide: NZ_MODAL_CONFIG, useValue: { nzMask: false }}` to `providers` of your module, you can import `NZ_MODAL_CONFIG` from `ng-zorro-antd`)

The weight of global configuration, component default value, component input value:

component input value > global configuration > component default value

supported global configuration item
```ts
{
provide: NZ_MODAL_CONFIG,
useValue: {
nzMask?: boolean; // Whether show mask or not.
nzMaskClosable?: boolean; // Whether to close the modal dialog when the mask (area outside the modal) is clicked
}
}
```
> Note: global configuration does not have default value which component has it.
#### ModalButtonOptions (used to customize the bottom button)

An array of `ModalButtonOptions` type can be passed to `nzFooter` for custom bottom buttons.
Expand Down
23 changes: 23 additions & 0 deletions components/modal/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,29 @@ constructor(modal: NzModalService) {
| triggerOk() | 手动触发nzOnOk |
| triggerCancel() | 手动触发nzOnCancel |


### 全局配置

全局配置(NZ_MODAL_CONFIG)
如果要进行全局默认配置,你可以设置提供商 `NZ_MODAL_CONFIG` 的值来实现。
(如:在你的模块的`providers`中加入 `{ provide: NZ_MODAL_CONFIG, useValue: { nzMask: false }}``NZ_MODAL_CONFIG` 可以从 `ng-zorro-antd` 中导入)

全局配置,组件默认值,组件层级配置之间的权重如下:

组件层级配置 > 全局配置 > 组件默认值

当前支持的全局配置
```ts
{
provide: NZ_MODAL_CONFIG,
useValue: {
nzMask?: boolean; // 是否展示遮罩
nzMaskClosable?: boolean; // 点击蒙层是否允许关闭
}
}
```
注:全局配置并无默认值,因为nzMask和nzMaskClosable默认值存在于组件中

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

可将此类型数组传入 `nzFooter`,用于自定义底部按钮。
Expand Down
16 changes: 3 additions & 13 deletions components/modal/nz-modal-config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { InjectionToken } from '@angular/core';

export const NZ_MODAL_DEFAULT_CONFIG: NzModalConfig = {
autoBodyPadding: true
};

export const NZ_MODAL_CONFIG = new InjectionToken<NzModalConfig>('NzModalConfig', {
providedIn: 'root',
factory: () => NZ_MODAL_DEFAULT_CONFIG // Default config
});

export interface NzModalConfig {
/**
* @deprecated used {@link BlockScrollStrategy} instead.
*/
autoBodyPadding?: boolean; // Whether add the padding-right and overflow to body automatically to play smoothly
nzMask?: boolean;
nzMaskClosable?: boolean;
}
export const NZ_MODAL_CONFIG = new InjectionToken<NzModalConfig>('NZ_MODAL_CONFIG');
2 changes: 1 addition & 1 deletion components/modal/nz-modal.component.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<ng-template #tplOriginContent><ng-content></ng-content></ng-template> <!-- Compatible: the <ng-content> can appear only once -->

<div [nzNoAnimation]="nzNoAnimation">
<div *ngIf="nzMask"
<div *ngIf="mask"
class="ant-modal-mask"
[ngClass]="maskAnimationClassMap"
[class.ant-modal-mask-hidden]="hidden"
Expand Down
52 changes: 41 additions & 11 deletions components/modal/nz-modal.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
OnChanges,
OnDestroy,
OnInit,
Optional,
Output,
SimpleChanges,
TemplateRef,
Expand All @@ -33,7 +34,7 @@ import { InputBoolean } from '../core/util/convert';
import { isPromise } from '../core/util/is-promise';
import { NzI18nService } from '../i18n/nz-i18n.service';
import ModalUtil from './modal-util';
import { NzModalConfig, NZ_MODAL_CONFIG, NZ_MODAL_DEFAULT_CONFIG } from './nz-modal-config';
import { NzModalConfig, NZ_MODAL_CONFIG } from './nz-modal-config';
import { NzModalControlService } from './nz-modal-control.service';
import { NzModalRef } from './nz-modal-ref.class';
import { ModalButtonOptions, ModalOptions, ModalType, OnClickCallback } from './nz-modal.type';
Expand All @@ -54,14 +55,14 @@ export class NzModalComponent<T = any, R = any> extends NzModalRef<T, R>
implements OnInit, OnChanges, AfterViewInit, OnDestroy, ModalOptions<T> {
@Input() @InputBoolean() nzVisible: boolean = false;
@Input() @InputBoolean() nzClosable: boolean = true;
@Input() @InputBoolean() nzMask: boolean = true;
@Input() @InputBoolean() nzMaskClosable: boolean = true;
@Input() @InputBoolean() nzOkLoading: boolean = false;
@Input() @InputBoolean() nzOkDisabled: boolean = false;
@Input() @InputBoolean() nzCancelDisabled: boolean = false;
@Input() @InputBoolean() nzCancelLoading: boolean = false;
@Input() @InputBoolean() nzKeyboard: boolean = true;
@Input() @InputBoolean() nzNoAnimation = false;
@Input() @InputBoolean() nzMask: boolean;
@Input() @InputBoolean() nzMaskClosable: boolean;
@Input() nzContent: string | TemplateRef<{}> | Type<T>; // [STATIC] If not specified, will use <ng-content>
@Input() nzComponentParams: T; // [STATIC] ONLY avaliable when nzContent is a component
@Input() nzFooter: string | TemplateRef<{}> | Array<ModalButtonOptions<T>> | null; // [STATIC] Default Modal ONLY
Expand Down Expand Up @@ -113,6 +114,40 @@ export class NzModalComponent<T = any, R = any> extends NzModalRef<T, R>
return !this.nzVisible && !this.animationState;
} // Indicate whether this dialog should hidden

/**
* @description
* The calculated highest weight of mask value
*
* Weight of different mask input:
* component default value < global configuration < component input value
*/
get mask(): boolean {
if (this.nzMask != null) {
return this.nzMask;
} else if (this.nzModalGlobalConfig && this.nzModalGlobalConfig.nzMask != null) {
return this.nzModalGlobalConfig.nzMask;
} else {
return true;
}
}

/**
* @description
* The calculated highest weight of maskClosable value
*
* Weight of different maskClosable input:
* component default value < global configuration < component input value
*/
get maskClosable(): boolean {
if (this.nzMaskClosable != null) {
return this.nzMaskClosable;
} else if (this.nzModalGlobalConfig && this.nzModalGlobalConfig.nzMaskClosable != null) {
return this.nzModalGlobalConfig.nzMaskClosable;
} else {
return true;
}
}

locale: { okText?: string; cancelText?: string } = {};
maskAnimationClassMap: object | null;
modalAnimationClassMap: object | null;
Expand All @@ -137,11 +172,10 @@ export class NzModalComponent<T = any, R = any> extends NzModalRef<T, R>
private modalControl: NzModalControlService,
private focusTrapFactory: FocusTrapFactory,
private cdr: ChangeDetectorRef,
@Inject(NZ_MODAL_CONFIG) private config: NzModalConfig,
@Optional() @Inject(NZ_MODAL_CONFIG) private nzModalGlobalConfig: NzModalConfig,
@Inject(DOCUMENT) private document: any // tslint:disable-line:no-any
) {
super();
this.config = this.mergeDefaultConfig(this.config);
this.scrollStrategy = this.overlay.scrollStrategies.block();
}

Expand Down Expand Up @@ -256,8 +290,8 @@ export class NzModalComponent<T = any, R = any> extends NzModalRef<T, R>

onClickMask($event: MouseEvent): void {
if (
this.nzMask &&
this.nzMaskClosable &&
this.mask &&
this.maskClosable &&
($event.target as HTMLElement).classList.contains('ant-modal-wrap') &&
this.nzVisible
) {
Expand Down Expand Up @@ -444,10 +478,6 @@ export class NzModalComponent<T = any, R = any> extends NzModalRef<T, R>
}
}

private mergeDefaultConfig(config: NzModalConfig): NzModalConfig {
return { ...NZ_MODAL_DEFAULT_CONFIG, ...config };
}

private savePreviouslyFocusedElement(): void {
if (this.document) {
this.previouslyFocusedElement = this.document.activeElement as HTMLElement;
Expand Down
61 changes: 61 additions & 0 deletions components/modal/nz-modal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import en_US from '../i18n/languages/en_US';
import { NzI18nService } from '../i18n/nz-i18n.service';
import { NzIconTestModule } from '../icon/nz-icon-test.module';
import { CssUnitPipe } from './css-unit.pipe';
import { NZ_MODAL_CONFIG } from './nz-modal-config';
import { NzModalControlService } from './nz-modal-control.service';
import { NzModalRef } from './nz-modal-ref.class';
import { NzModalComponent } from './nz-modal.component';
Expand Down Expand Up @@ -370,6 +371,54 @@ describe('modal testing (legacy)', () => {
});
});

describe('global config', () => {
let basicFixture: ComponentFixture<NzDemoModalBasicComponent>;
let inputFixture: ComponentFixture<NzDemoModalWithInputComponent>;
let nativeElement: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, NzModalModule],
providers: [
{
provide: NZ_MODAL_CONFIG,
useValue: {
nzMask: false,
nzMaskClosable: false
}
}
],
declarations: [NzDemoModalBasicComponent, NzDemoModalWithInputComponent]
}).compileComponents();
basicFixture = TestBed.createComponent<NzDemoModalBasicComponent>(NzDemoModalBasicComponent);
inputFixture = TestBed.createComponent<NzDemoModalWithInputComponent>(NzDemoModalWithInputComponent);
});

it('nzMask should be global config value', fakeAsync(() => {
const debugElement = basicFixture.debugElement.query(By.css('.ant-modal-mask'));
basicFixture.detectChanges();
expect(debugElement).toBeNull();
}));

it('nzMask should be input value', fakeAsync(() => {
inputFixture.componentInstance.nzMask = true;
inputFixture.detectChanges();
nativeElement = inputFixture.debugElement.query(By.css('.ant-modal-mask')).nativeElement;
inputFixture.detectChanges();
expect(nativeElement).not.toBeNull();
}));

it('nzMaskClosable should be global config value', fakeAsync(() => {
inputFixture.componentInstance.nzMask = true;
inputFixture.detectChanges();
nativeElement = inputFixture.debugElement.query(By.css('.ant-modal-wrap')).nativeElement;
inputFixture.detectChanges();
nativeElement!.click();
inputFixture.detectChanges();
console.log(inputFixture.debugElement.nativeElement);
expectModalHidden(inputFixture.debugElement.query(By.css('nz-modal')).nativeElement, true);
}));
});

describe('NzModal', () => {
let modalService: NzModalService;
let overlayContainer: OverlayContainer;
Expand Down Expand Up @@ -627,6 +676,18 @@ class NzDemoModalBasicComponent {
modalAvailable = true;
}

@Component({
template: `
<nz-modal *ngIf="modalAvailable" [nzMask]="nzMask">
<p>content</p>
</nz-modal>
`
})
class NzDemoModalWithInputComponent {
modalAvailable = true;
nzMask = true;
}

@Component({
selector: 'nz-demo-modal-async',
template: `
Expand Down

0 comments on commit b575d91

Please sign in to comment.