Skip to content

Commit

Permalink
feat(module:*): global config
Browse files Browse the repository at this point in the history
poc: use decorator to extract property
  • Loading branch information
Wendell committed Jun 17, 2019
1 parent e59171b commit 145593a
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 11 deletions.
43 changes: 33 additions & 10 deletions components/button/nz-button.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,25 @@ import {
findLastNotEmptyNode,
isEmpty,
InputBoolean,
NzConfigService,
NzSizeLDSType,
NzSizeMap,
NzUpdateHostClassService,
NzWaveConfig,
NzWaveDirective,
NZ_WAVE_GLOBAL_CONFIG
NZ_WAVE_GLOBAL_CONFIG,
PropWithConfig
} from 'ng-zorro-antd/core';
import { NzIconDirective } from 'ng-zorro-antd/icon';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';

export type NzButtonType = 'primary' | 'dashed' | 'danger' | 'default' | 'link';
export type NzButtonShape = 'circle' | 'round' | null;

const componentName = 'nzButton';
const WithConfig = PropWithConfig(componentName);

@Component({
selector: '[nz-button]',
exportAs: 'nzButton',
Expand All @@ -56,9 +63,6 @@ export type NzButtonShape = 'circle' | 'round' | null;
templateUrl: './nz-button.component.html'
})
export class NzButtonComponent implements AfterContentInit, OnInit, OnDestroy, OnChanges {
readonly el: HTMLElement = this.elementRef.nativeElement;
private iconElement: HTMLElement;
private iconOnly = false;
@ViewChild('contentElement', { static: true }) contentElement: ElementRef;
@ContentChildren(NzIconDirective, { read: ElementRef }) listOfIconElement: QueryList<ElementRef>;
@HostBinding('attr.nz-wave') nzWave = new NzWaveDirective(
Expand All @@ -67,13 +71,20 @@ export class NzButtonComponent implements AfterContentInit, OnInit, OnDestroy, O
this.waveConfig,
this.animationType
);
@Input() @InputBoolean() nzBlock = false;
@Input() @InputBoolean() nzGhost = false;
@Input() @InputBoolean() nzSearch = false;
@Input() @InputBoolean() nzLoading = false;

@Input() @WithConfig(false) @InputBoolean() nzBlock: boolean;
@Input() @InputBoolean() nzGhost: boolean = false;
@Input() @InputBoolean() nzSearch: boolean = false;
@Input() @InputBoolean() nzLoading: boolean = false;
@Input() nzType: NzButtonType = 'default';
@Input() nzShape: NzButtonShape = null;
@Input() nzSize: NzSizeLDSType = 'default';
@Input() @WithConfig(null) nzShape: NzButtonShape;
@Input() @WithConfig('default') nzSize: NzSizeLDSType;

readonly el: HTMLElement = this.elementRef.nativeElement;

private iconElement: HTMLElement;
private iconOnly = false;
private destroy$ = new Subject<void>();

/** temp solution since no method add classMap to host https://github.com/angular/angular/issues/7289 */
setClassMap(): void {
Expand Down Expand Up @@ -135,10 +146,20 @@ export class NzButtonComponent implements AfterContentInit, OnInit, OnDestroy, O
private renderer: Renderer2,
private nzUpdateHostClassService: NzUpdateHostClassService,
private ngZone: NgZone,
public nzConfigService: NzConfigService,
@Optional() @Inject(NZ_WAVE_GLOBAL_CONFIG) private waveConfig: NzWaveConfig,
@Optional() @Inject(ANIMATION_MODULE_TYPE) private animationType: string
) {
this.renderer.addClass(elementRef.nativeElement, 'ant-btn');
this.nzConfigService.configUpdated$
.pipe(
takeUntil(this.destroy$),
filter(n => n === componentName)
)
.subscribe(() => {
this.setClassMap();
this.cdr.markForCheck();
});
}

ngAfterContentInit(): void {
Expand All @@ -151,6 +172,8 @@ export class NzButtonComponent implements AfterContentInit, OnInit, OnDestroy, O
}

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

Expand Down
36 changes: 36 additions & 0 deletions components/core/config/config.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @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
*/

// tslint:disable no-any

import { Inject, Injectable, Optional } from '@angular/core';
import { Subject } from 'rxjs';

import { NzConfig, NZ_CONFIG } from './config';

@Injectable({
providedIn: 'root'
})
export class NzConfigService {
configUpdated$ = new Subject<string>();
config: NzConfig;

constructor(@Optional() @Inject(NZ_CONFIG) defaultConfig?: NzConfig) {
this.config = defaultConfig || {};
}

getDefaultConfig(componentName: keyof NzConfig, propName: string): any {
const componentConfig: any = this.config[componentName] || {};
return componentConfig[propName] || null;
}

set(componentName: keyof NzConfig, value?: any): void {
this.config[componentName] = { ...this.config[componentName], ...(value || {}) };
this.configUpdated$.next(componentName);
}
}
24 changes: 24 additions & 0 deletions components/core/config/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @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 { InjectionToken } from '@angular/core';

export interface NzConfig {
nzButton?: NzButtonConfig;
}

export interface NzButtonConfig {
nzSize?: 'default' | 'large' | 'small';
nzShape?: 'circle' | 'round';
nzBlock?: boolean;
}

/**
* User should provide an object implements this interface to set global configurations.
*/
export const NZ_CONFIG = new InjectionToken<NzConfig>('nz-config');
9 changes: 9 additions & 0 deletions components/core/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @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
*/

export * from './public-api';
11 changes: 11 additions & 0 deletions components/core/config/public-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @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
*/

export * from './config.service';
export * from './config';
export * from './utils';
50 changes: 50 additions & 0 deletions components/core/config/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* @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 { Type } from '@angular/core';

// tslint:disable:no-invalid-this
// tslint:disable:no-any

// export function ComponentWithConfig<T>(type: Type<T>): (t: any) => void {
// return function(target: any): void {};
// }

import { NzConfigService } from 'ng-zorro-antd';
import { NzConfig } from './config';

/**
* This decorator is used to decorate properties. If a property is decorated, it would try to load default value from
* config.
*/
// tslint:disable-next-line:typedef
export function PropWithConfig(componentName: keyof NzConfig) {
return function<T>(innerDefaultValue: T): (t: any, p: string) => void {
return function(target: any, propName: string): void {
const privatePropName = `$$__assignedValue__${propName}`;

if (Object.prototype.hasOwnProperty.call(target, privatePropName)) {
console.warn(`The prop "${privatePropName}" is already exist, it will be override by ${name} decorator.`);
}

Object.defineProperty(target, privatePropName, {
configurable: true,
writable: true
});

Object.defineProperty(target, propName, {
get(): T {
const defaultConfig = ((this.nzConfigService as NzConfigService).config[componentName] as any)[propName];
return this[privatePropName] || defaultConfig || innerDefaultValue;
},
set(value?: T): void {
this[privatePropName] = value;
}
});
};
};
}
1 change: 1 addition & 0 deletions components/core/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * from './wave/public-api';
export * from './dropdown/public-api';
export * from './logger/public-api';
export * from './responsive/public-api';
export * from './config/public-api';
2 changes: 1 addition & 1 deletion components/core/util/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function propDecoratorFactory<T, D>(name: string, fallback: (v: T) => D): (targe
const privatePropName = `$$__${propName}`;

if (Object.prototype.hasOwnProperty.call(target, privatePropName)) {
console.warn(`The prop "${privatePropName}" is already exist, it will be overrided by ${name} decorator.`);
console.warn(`The prop "${privatePropName}" is already exist, it will be override by ${name} decorator.`);
}

Object.defineProperty(target, privatePropName, {
Expand Down

0 comments on commit 145593a

Please sign in to comment.