55
66import { CSP_NONCE , Injectable , inject } from '@angular/core' ;
77import { Observable , Subject } from 'rxjs' ;
8- import { filter , mapTo } from 'rxjs/operators' ;
8+ import { filter , map } from 'rxjs/operators' ;
99
1010import { NzSafeAny } from 'ng-zorro-antd/core/types' ;
1111
@@ -47,7 +47,7 @@ export class NzConfigService {
4747 getConfigChangeEventForComponent ( componentName : NzConfigKey ) : Observable < void > {
4848 return this . configUpdated$ . pipe (
4949 filter ( n => n === componentName ) ,
50- mapTo ( undefined )
50+ map ( ( ) => undefined )
5151 ) ;
5252 }
5353
@@ -60,51 +60,51 @@ export class NzConfigService {
6060 }
6161}
6262
63- /* eslint-disable no-invalid-this */
64-
6563/**
66- * This decorator is used to decorate properties. If a property is decorated, it would try to load default value from
67- * config.
64+ * This decorator is used to decorate class field. If a class field is decorated and unassigned, it would try to load default value from `NZ_CONFIG`
65+ *
66+ * @note that the class must have `_nzModuleName`({@link NzConfigKey}) property.
67+ * @example
68+ * ```ts
69+ * class ExampleComponent {
70+ * private readonly _nzModuleName: NzConfigKey = 'button';
71+ * @WithConfig () size: string = 'default';
72+ * }
73+ * ```
6874 */
69- // eslint-disable-next-line
70- export function WithConfig < T > ( ) {
71- return function ConfigDecorator (
72- target : NzSafeAny ,
73- propName : NzSafeAny ,
74- originalDescriptor ?: TypedPropertyDescriptor < T >
75- ) : NzSafeAny {
76- const privatePropName = `$$__zorroConfigDecorator__${ propName } ` ;
77-
78- Object . defineProperty ( target , privatePropName , {
79- configurable : true ,
80- writable : true ,
81- enumerable : false
82- } ) ;
75+ export function WithConfig < This , Value > ( ) {
76+ return function ( _value : undefined , context : ClassFieldDecoratorContext < This , Value > ) {
77+ context . addInitializer ( function ( ) {
78+ const nzConfigService = inject ( NzConfigService ) ;
79+ const originalValue = this [ context . name as keyof This ] ;
80+
81+ let value : Value ;
82+ let assignedByUser = false ;
83+
84+ Object . defineProperty ( this , context . name , {
85+ get : ( ) => {
86+ const configValue = nzConfigService . getConfigForComponent (
87+ this [ '_nzModuleName' as keyof This ] as NzConfigKey
88+ ) ?. [ context . name as keyof NzConfig [ NzConfigKey ] ] ;
89+
90+ if ( assignedByUser ) {
91+ return value ;
92+ }
93+
94+ if ( isDefined ( configValue ) ) {
95+ return configValue ;
96+ }
8397
84- return {
85- get ( ) : T | undefined {
86- const originalValue = originalDescriptor ?. get ? originalDescriptor . get . bind ( this ) ( ) : this [ privatePropName ] ;
87- const assignedByUser = ( this . propertyAssignCounter ?. [ propName ] || 0 ) > 1 ;
88- const configValue = this . nzConfigService . getConfigForComponent ( this . _nzModuleName ) ?. [ propName ] ;
89- if ( assignedByUser && isDefined ( originalValue ) ) {
9098 return originalValue ;
91- } else {
92- return isDefined ( configValue ) ? configValue : originalValue ;
93- }
94- } ,
95- set ( value ?: T ) : void {
96- // If the value is assigned, we consider the newly assigned value as 'assigned by user'.
97- this . propertyAssignCounter = this . propertyAssignCounter || { } ;
98- this . propertyAssignCounter [ propName ] = ( this . propertyAssignCounter [ propName ] || 0 ) + 1 ;
99-
100- if ( originalDescriptor ?. set ) {
101- originalDescriptor . set . bind ( this ) ( value ! ) ;
102- } else {
103- this [ privatePropName ] = value ;
104- }
105- } ,
106- configurable : true ,
107- enumerable : true
108- } ;
99+ } ,
100+ set : ( newValue : Value ) => {
101+ // if the newValue is undefined, we also consider it as not assigned by user
102+ assignedByUser = isDefined ( newValue ) ;
103+ value = newValue ;
104+ } ,
105+ enumerable : true ,
106+ configurable : true
107+ } ) ;
108+ } ) ;
109109 } ;
110110}
0 commit comments