@@ -19,6 +19,7 @@ import { InvalidDate } from '../utils/constant'
19
19
import { deepEqual } from '../utils/deepEqual'
20
20
import { isRadioOrCheckboxInput } from '../utils/fieldElement'
21
21
import { getFormEl } from '../utils/getFormEl'
22
+ import { getPath } from '../utils/getPath'
22
23
import { getValidationMode } from '../utils/getValidationMode'
23
24
import { isFieldElement } from '../utils/isFieldElement'
24
25
@@ -55,6 +56,7 @@ export function creatFormControl<
55
56
type TFormStateKey = keyof TFormState
56
57
57
58
const _fields = { } as Fields < TFieldValues , FieldsKey >
59
+ const _originalFieldsKey = new Set < string > ( )
58
60
59
61
const _formState = reactive < TFormState > ( {
60
62
isDirty : false ,
@@ -98,22 +100,25 @@ export function creatFormControl<
98
100
const paths = toPath ( fieldName )
99
101
100
102
if ( paths . length !== 1 ) {
101
- let error : any = _formState . errors
102
- for ( const path of paths . slice ( 0 , - 1 ) ) {
103
- error = error [ path ]
104
- }
103
+ const error = getPath ( fieldName as string , _formState . errors , - 1 )
105
104
unset ( error , paths . at ( - 1 ) )
106
105
} else {
107
106
unset ( _formState . errors , fieldName )
108
107
}
109
108
}
110
109
110
+ const _getField = ( name : FieldsKey ) => {
111
+ return getPath ( name as string , _fields ) as Field | undefined
112
+ }
113
+
111
114
const _setFields = ( name : FieldsKey , fieldOptions : Partial < Field > ) => {
112
115
// init field
113
- const field = get ( _fields , name )
114
- if ( isNullOrUndefined ( field ) ) set ( _fields , name , { } )
116
+ const field = _getField ( name )
117
+ if ( isNullOrUndefined ( field ) ) {
118
+ setWith ( _fields , name , { } )
119
+ }
115
120
116
- set ( _fields , name , { ...field , ...fieldOptions } )
121
+ setWith ( _fields , name , { ...field , ...fieldOptions } )
117
122
}
118
123
119
124
const _getDefaultValue = ( field : FieldsKey ) => {
@@ -124,11 +129,11 @@ export function creatFormControl<
124
129
_setFormState ( { isValidating } )
125
130
126
131
const _getFieldDom = ( name : FieldsKey ) => {
127
- return _fields [ name ] . el . value as FieldElement | undefined
132
+ return _getField ( name ) . el . value as FieldElement | undefined
128
133
}
129
134
130
135
const _isDirtyField = ( fieldName : FieldsKey ) => {
131
- const field = _fields [ fieldName ]
136
+ const field = _getField ( fieldName )
132
137
133
138
if ( ! field ) {
134
139
return false
@@ -156,14 +161,14 @@ export function creatFormControl<
156
161
const _getDirtyFields = ( handleIsDirty = true ) => {
157
162
const dirtyFields = { } as TFormState [ 'dirtyFields' ]
158
163
159
- Object . keys ( _fields ) . forEach ( ( key ) => {
164
+ for ( const key of _originalFieldsKey . keys ( ) ) {
160
165
if ( _isDirtyField ( key ) ) {
161
166
set ( dirtyFields , key , true )
162
167
} else {
163
168
unset ( dirtyFields , key )
164
- _fields [ key ] . isDirty = false
169
+ _getField ( key ) . isDirty = false
165
170
}
166
- } )
171
+ }
167
172
168
173
if ( handleIsDirty ) {
169
174
_setFormState ( {
@@ -175,10 +180,14 @@ export function creatFormControl<
175
180
}
176
181
177
182
const _handleDirtyField = ( fieldName : FieldsKey ) => {
178
- if ( _fields [ fieldName ] . isUnregistered ) return
183
+ const field = _getField ( fieldName )
184
+
185
+ if ( field . isUnregistered ) {
186
+ return
187
+ }
179
188
180
189
const defaultVal = get ( _defaultValues , fieldName as string )
181
- const val = _fields [ fieldName ] . inputValue . value
190
+ const val = field . inputValue . value
182
191
183
192
if ( deepEqual ( defaultVal , val ) ) {
184
193
_setFields ( fieldName , {
@@ -196,9 +205,9 @@ export function creatFormControl<
196
205
fieldNames ?: FieldsKey | FieldsKey [ ]
197
206
) => {
198
207
if ( isUndefined ( fieldNames ) ) {
199
- Object . keys ( _fields ) . forEach ( ( fieldName ) => {
208
+ for ( const fieldName of _originalFieldsKey . keys ( ) ) {
200
209
_handleDirtyField ( fieldName )
201
- } )
210
+ }
202
211
} else if ( ! isArray ( fieldNames ) ) {
203
212
fieldNames = [ fieldNames ]
204
213
@@ -223,7 +232,7 @@ export function creatFormControl<
223
232
fieldName : FieldsKey ,
224
233
isValidateAllFields = false
225
234
) => {
226
- const field = _fields [ fieldName ]
235
+ const field = _getField ( fieldName )
227
236
228
237
if ( isEmptyObject ( _fields ) || isNullOrUndefined ( field ) ) {
229
238
return
@@ -289,7 +298,7 @@ export function creatFormControl<
289
298
if (
290
299
isFunction ( resolver ) &&
291
300
isEmptyObject ( res ) &&
292
- ! isEmptyObject ( _fields [ fieldName ] . rule )
301
+ ! isEmptyObject ( _getField ( fieldName ) . rule )
293
302
)
294
303
res = await validateField (
295
304
field ,
@@ -317,7 +326,7 @@ export function creatFormControl<
317
326
318
327
const _validateAllFields = async ( ) => {
319
328
_setValidating ( true )
320
- for ( const fieldName of Object . keys ( _fields ) )
329
+ for ( const fieldName of _originalFieldsKey . keys ( ) )
321
330
await _validate ( fieldName , true )
322
331
323
332
_setValidating ( false )
@@ -354,13 +363,14 @@ export function creatFormControl<
354
363
}
355
364
356
365
Object . entries ( values ) . forEach ( ( [ key , val ] ) => {
357
- const el = _fields [ key ] . el . value
366
+ const field = _getField ( key )
367
+ const el = field . el . value
358
368
359
369
if ( ! keepStateOptions . keepDefaultValues ) {
360
370
_formState . defaultValues [ key as keyof TFieldValues ] = val
361
371
}
362
372
if ( ! keepStateOptions . keepValues ) {
363
- _fields [ key ] . inputValue . value = val
373
+ field . inputValue . value = val
364
374
}
365
375
if ( isRadioOrCheckboxInput ( el ) ) {
366
376
el . checked = val
@@ -418,8 +428,8 @@ export function creatFormControl<
418
428
}
419
429
420
430
const res : Record < string , any > = { }
421
- for ( const fieldName of Object . keys ( _fields ) ) {
422
- res [ fieldName ] = _fields [ fieldName ] . inputValue
431
+ for ( const fieldName of _originalFieldsKey . keys ( ) ) {
432
+ res [ fieldName ] = _getField ( fieldName ) . inputValue
423
433
}
424
434
425
435
await onSubmit ( _fields as UnpackNestedValue < TFieldValues > , e )
@@ -439,7 +449,7 @@ export function creatFormControl<
439
449
_setFormStateError ( fieldName , {
440
450
message : '' ,
441
451
...error ,
442
- el : _fields [ fieldName ] . el ,
452
+ el : _getField ( fieldName ) . el ,
443
453
} as FieldError )
444
454
445
455
_setFormState ( {
@@ -466,15 +476,29 @@ export function creatFormControl<
466
476
}
467
477
468
478
const _setFieldsValue = ( name : FieldsKey , value : TFieldValues [ FieldsKey ] ) => {
469
- _fields [ name ] . inputValue . value = value
479
+ const field = _getField ( name )
480
+ const el = field . el . value
481
+
482
+ field . inputValue . value = value
483
+
484
+ if ( isRadioOrCheckboxInput ( el ) ) {
485
+ el . checked = value
486
+ }
487
+ }
488
+
489
+ const _setField = ( name : FieldsKey , options : TFieldValues [ FieldsKey ] ) => {
490
+ setWith ( _fields , name , {
491
+ ..._getField ( name ) ,
492
+ ..._options ,
493
+ } )
470
494
}
471
495
472
496
const setValue : UseFormSetValue < TFieldValues , FieldsKey > = async (
473
497
name ,
474
498
value ,
475
499
config = { }
476
500
) => {
477
- if ( isNullOrUndefined ( _fields [ name ] ) ) {
501
+ if ( isNullOrUndefined ( _getField ( name ) ) ) {
478
502
warn ( `setValue cannot set not exist field #${ name as string } ` )
479
503
return
480
504
}
@@ -487,9 +511,13 @@ export function creatFormControl<
487
511
488
512
_setFieldsValue ( name , value )
489
513
490
- if ( config . shouldDirty ) _handleAllDirtyFieldsOperate ( name )
514
+ if ( config . shouldDirty ) {
515
+ _handleAllDirtyFieldsOperate ( name )
516
+ }
491
517
492
- if ( config . shouldValidate ) await trigger ( name )
518
+ if ( config . shouldValidate ) {
519
+ await trigger ( name )
520
+ }
493
521
}
494
522
495
523
const setFocus : UseFormSetFocus < TFieldValues > = ( name ) =>
@@ -503,14 +531,14 @@ export function creatFormControl<
503
531
const res : GetValuesReturn < FieldValues , FieldsKey > = { }
504
532
505
533
if ( isUndefined ( fieldNames ) ) {
506
- Object . entries ( _fields ) . forEach ( ( [ name , field ] ) => {
507
- set ( res , name , field . inputValue . value )
508
- } )
534
+ for ( const name of _originalFieldsKey . keys ( ) ) {
535
+ set ( res , name , _getField ( name ) . inputValue . value )
536
+ }
509
537
} else {
510
538
if ( ! isArray ( fieldNames ) ) fieldNames = [ fieldNames ]
511
539
512
540
fieldNames . forEach ( ( name ) => {
513
- set ( res , name as string , _fields [ name ] . inputValue . value )
541
+ set ( res , name as string , _getField ( name ) . inputValue . value )
514
542
} )
515
543
}
516
544
@@ -532,9 +560,10 @@ export function creatFormControl<
532
560
if ( isUndefined ( options ) ) {
533
561
options = { }
534
562
}
563
+ _originalFieldsKey . add ( fieldName )
535
564
536
565
let isModelValue = false
537
- let field = get ( _fields , fieldName )
566
+ let field = _getField ( fieldName )
538
567
539
568
const { vModelBinding = 'modelValue' } = options
540
569
@@ -557,23 +586,23 @@ export function creatFormControl<
557
586
isUnregistered : false ,
558
587
el : ref ( null ) ,
559
588
} )
560
- field = get ( _fields , fieldName )
589
+ field = _getField ( fieldName )
561
590
562
591
nextTick ( ( ) => {
563
592
const el = field . el . value
564
- if ( el instanceof HTMLElement && isRadioOrCheckboxInput ( el ) ) {
593
+ if ( el instanceof HTMLInputElement && isRadioOrCheckboxInput ( el ) ) {
565
594
el . checked = defaultVal === '' ? false : defaultVal
566
595
}
567
596
} )
568
597
}
569
598
570
599
const addEventListenerToElement = ( ) => {
571
- if ( isFieldElement ( field . el ) || _fields [ fieldName ] . isUnregistered ) {
600
+ if ( isFieldElement ( field . el ) || field . isUnregistered ) {
572
601
return
573
602
}
574
603
575
604
const el = getFormEl ( field . el )
576
- _fields [ fieldName ] . el . value = el
605
+ field . el . value = el
577
606
578
607
if ( isRadioOrCheckboxInput ( el ) ) {
579
608
set ( _defaultValues , fieldName as string , ! ! defaultVal )
@@ -604,12 +633,12 @@ export function creatFormControl<
604
633
605
634
return {
606
635
// avoid rebinding ref
607
- ...( ! isFieldElement ( field . el ) && { ref : _fields [ fieldName ] . el } ) ,
636
+ ...( ! isFieldElement ( field . el ) && { ref : field . el } ) ,
608
637
609
638
...( vModelBinding === 'modelValue' && {
610
639
value : field . inputValue . value ,
611
640
onInput : ( e ) => {
612
- if ( _fields [ fieldName ] . isUnregistered ) return
641
+ if ( field . isUnregistered ) return
613
642
614
643
addEventListenerToElement ( )
615
644
queueMicrotask ( ( ) => {
@@ -622,7 +651,7 @@ export function creatFormControl<
622
651
623
652
[ vModelBinding ] : field . inputValue . value ,
624
653
[ `onUpdate:${ vModelBinding } ` ] : ( input : any ) => {
625
- if ( _fields [ fieldName ] . isUnregistered ) return
654
+ if ( field . isUnregistered ) return
626
655
627
656
isModelValue = true
628
657
addEventListenerToElement ( )
@@ -635,7 +664,7 @@ export function creatFormControl<
635
664
fieldName ,
636
665
options = { }
637
666
) => {
638
- if ( isNullOrUndefined ( _fields [ fieldName ] ) ) {
667
+ if ( isNullOrUndefined ( _getField ( fieldName ) ) ) {
639
668
warn ( `cannot unregister not exist field #${ fieldName as string } ` )
640
669
return
641
670
}
@@ -662,11 +691,13 @@ export function creatFormControl<
662
691
)
663
692
}
664
693
665
- set ( _fields [ fieldName as string ] , 'isUnregistered' , true )
694
+ _setFields ( fieldName , {
695
+ isUnregistered : true ,
696
+ } )
666
697
}
667
698
668
699
const isExistInErrors = ( fieldName : keyof TFieldValues ) =>
669
- Object . keys ( _formState . errors ) . includes ( fieldName as string )
700
+ ! isEmptyObject ( getPath ( fieldName as string , _formState . errors ) )
670
701
671
702
return {
672
703
control : {
0 commit comments