1
1
import { Inject , Injectable , Optional } from '@angular/core' ;
2
2
import { AbstractControl , FormArray , FormControl , FormGroup } from '@angular/forms' ;
3
- import { clone , coerceArray , filterControlKeys , filterNil , isBrowser } from './utils' ;
3
+ import { clone , coerceArray , filterControlKeys , filterNil , isBrowser , mergeDeep } from './utils' ;
4
4
import { merge , Observable , Subscription } from 'rxjs' ;
5
5
import { debounceTime , distinctUntilChanged , map } from 'rxjs/operators' ;
6
6
import { FormsStore } from './forms-manager.store' ;
@@ -30,7 +30,9 @@ export class NgFormsManager<FormsState = any> {
30
30
return this . selectControl ( formName , path ) . pipe ( map ( control => control . disabled ) ) ;
31
31
}
32
32
33
- selectValue < T extends keyof FormsState > ( formName : T , path ?: string ) : Observable < FormsState [ T ] > {
33
+ selectValue < T extends keyof FormsState > ( formName : T , path ?: string ) : Observable < FormsState [ T ] > ;
34
+ selectValue < T = any > ( formName : keyof FormsState , path : string ) : Observable < T > ;
35
+ selectValue ( formName : keyof FormsState , path ?: string ) : Observable < any > {
34
36
return this . selectControl ( formName , path ) . pipe ( map ( control => control . value ) ) ;
35
37
}
36
38
@@ -41,9 +43,12 @@ export class NgFormsManager<FormsState = any> {
41
43
/**
42
44
* If no path specified it means that it's a single FormControl or FormArray
43
45
*/
44
- selectControl ( formName : keyof FormsState , path ?: string ) : Observable < _AbstractControl > {
46
+ selectControl < T = any > (
47
+ formName : keyof FormsState ,
48
+ path ?: string
49
+ ) : Observable < _AbstractControl < T > > {
45
50
if ( ! path ) {
46
- return this . selectForm ( formName ) ;
51
+ return this . selectForm ( formName ) as any ;
47
52
}
48
53
49
54
return this . store
@@ -55,10 +60,9 @@ export class NgFormsManager<FormsState = any> {
55
60
) ;
56
61
}
57
62
58
- // TODO: _AbstractControl should take a generic that should type the `value` property
59
- getControl ( formName : keyof FormsState , path ?: string ) : _AbstractControl {
63
+ getControl < T = any > ( formName : keyof FormsState , path ?: string ) : _AbstractControl < T > {
60
64
if ( ! path ) {
61
- return this . getForm ( formName ) ;
65
+ return this . getForm ( formName ) as any ;
62
66
}
63
67
64
68
if ( this . hasForm ( formName ) ) {
@@ -69,11 +73,10 @@ export class NgFormsManager<FormsState = any> {
69
73
return null ;
70
74
}
71
75
72
- // TODO: _AbstractControl should take a generic that should type the `value` property
73
- selectForm (
74
- formName : keyof FormsState ,
76
+ selectForm < T extends keyof FormsState > (
77
+ formName : T ,
75
78
options : { filterNil : true } = { filterNil : true }
76
- ) : Observable < AbstractGroup > {
79
+ ) : Observable < AbstractGroup < FormsState [ T ] > > {
77
80
return this . store
78
81
. select ( state => state [ formName as any ] )
79
82
. pipe ( options . filterNil ? filterNil : s => s ) ;
@@ -98,31 +101,31 @@ export class NgFormsManager<FormsState = any> {
98
101
arrControlFactory ?: ControlFactory | HashMap < ControlFactory > ;
99
102
} = { }
100
103
) {
101
- const merged = this . config . merge ( config ) as Config & { arrControlFactory ; persistState } ;
104
+ const mergedConfig = this . config . merge ( config ) as Config & { arrControlFactory ; persistState } ;
102
105
if ( isBrowser ( ) && config . persistState && this . hasForm ( formName ) === false ) {
103
- const storageValue = this . getFromStorage ( merged . storage . key ) ;
106
+ const storageValue = this . getFromStorage ( mergedConfig . storage . key ) ;
104
107
if ( storageValue [ formName ] ) {
105
108
this . store . update ( {
106
- [ formName ] : storageValue [ formName ] ,
109
+ [ formName ] : mergeDeep ( this . buildFormStoreState ( formName , form ) , storageValue [ formName ] ) ,
107
110
} as Partial < FormsState > ) ;
108
111
}
109
112
}
110
113
111
114
/** If the form already exist, patch the form with the store value */
112
115
if ( this . hasForm ( formName ) === true ) {
113
- form . patchValue ( this . resolveStoreToForm ( formName , form , merged . arrControlFactory ) , {
116
+ form . patchValue ( this . resolveStoreToForm ( formName , form , mergedConfig . arrControlFactory ) , {
114
117
emitEvent : false ,
115
118
} ) ;
116
119
} else {
117
120
const value = this . updateStore ( formName , form ) ;
118
- this . updateStorage ( formName , value , merged ) ;
121
+ this . updateStorage ( formName , value , mergedConfig ) ;
119
122
}
120
123
121
124
const unsubscribe = merge ( form . valueChanges , form . statusChanges . pipe ( distinctUntilChanged ( ) ) )
122
- . pipe ( debounceTime ( merged . debounceTime ) )
125
+ . pipe ( debounceTime ( mergedConfig . debounceTime ) )
123
126
. subscribe ( ( ) => {
124
127
const value = this . updateStore ( formName , form ) ;
125
- this . updateStorage ( formName , value , merged ) ;
128
+ this . updateStorage ( formName , value , mergedConfig ) ;
126
129
} ) ;
127
130
128
131
this . valueChanges . set ( formName , unsubscribe ) ;
@@ -131,13 +134,27 @@ export class NgFormsManager<FormsState = any> {
131
134
return this ;
132
135
}
133
136
134
- patchValue ( formName : keyof FormsState , value : any , options ) {
137
+ patchValue < T extends keyof FormsState > (
138
+ formName : T ,
139
+ value : Partial < FormsState [ T ] > ,
140
+ options ?: {
141
+ onlySelf ?: boolean ;
142
+ emitEvent ?: boolean ;
143
+ }
144
+ ) {
135
145
if ( this . instances . has ( formName ) ) {
136
146
this . instances . get ( formName ) . patchValue ( value , options ) ;
137
147
}
138
148
}
139
149
140
- setValue ( formName : keyof FormsState , value : any , options ) {
150
+ setValue < T extends keyof FormsState > (
151
+ formName : keyof FormsState ,
152
+ value : FormsState [ T ] ,
153
+ options ?: {
154
+ onlySelf ?: boolean ;
155
+ emitEvent ?: boolean ;
156
+ }
157
+ ) {
141
158
if ( this . instances . has ( formName ) ) {
142
159
this . instances . get ( formName ) . setValue ( value , options ) ;
143
160
}
0 commit comments