8000 :bug: fix some bugs · vue-use-form/vue-use-form@e8dadfe · GitHub
[go: up one dir, main page]

Skip to content

Commit e8dadfe

Browse files
committed
🐛 fix some bugs
1 parent 3437d51 commit e8dadfe

File tree

2 files changed

+98
-43
lines changed

2 files changed

+98
-43
lines changed

packages/core/src/logic/creatFormControl.ts

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { InvalidDate } from '../utils/constant'
1919
import { deepEqual } from '../utils/deepEqual'
2020
import { isRadioOrCheckboxInput } from '../utils/fieldElement'
2121
import { getFormEl } from '../utils/getFormEl'
22+
import { getPath } from '../utils/getPath'
2223
import { getValidationMode } from '../utils/getValidationMode'
2324
import { isFieldElement } from '../utils/isFieldElement'
2425

@@ -55,6 +56,7 @@ export function creatFormControl<
5556
type TFormStateKey = keyof TFormState
5657

5758
const _fields = {} as Fields<TFieldValues, FieldsKey>
59+
const _originalFieldsKey = new Set<string>()
5860

5961
const _formState = reactive<TFormState>({
6062
isDirty: false,
@@ -98,22 +100,25 @@ export function creatFormControl<
98100
const paths = toPath(fieldName)
99101

100102
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)
105104
unset(error, paths.at(-1))
106105
} else {
107106
unset(_formState.errors, fieldName)
108107
}
109108
}
110109

110+
const _getField = (name: FieldsKey) => {
111+
return getPath(name as string, _fields) as Field | undefined
112+
}
113+
111114
const _setFields = (name: FieldsKey, fieldOptions: Partial<Field>) => {
112115
// 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+
}
115120

116-
set(_fields, name, { ...field, ...fieldOptions })
121+
setWith(_fields, name, { ...field, ...fieldOptions })
117122
}
118123

119124
const _getDefaultValue = (field: FieldsKey) => { F438
@@ -124,11 +129,11 @@ export function creatFormControl<
124129
_setFormState({ isValidating })
125130

126131
const _getFieldDom = (name: FieldsKey) => {
127-
return _fields[name].el.value as FieldElement | undefined
132+
return _getField(name).el.value as FieldElement | undefined
128133
}
129134

130135
const _isDirtyField = (fieldName: FieldsKey) => {
131-
const field = _fields[fieldName]
136+
const field = _getField(fieldName)
132137

133138
if (!field) {
134139
return false
@@ -156,14 +161,14 @@ export function creatFormControl<
156161
const _getDirtyFields = (handleIsDirty = true) => {
157162
const dirtyFields = {} as TFormState['dirtyFields']
158163

159-
Object.keys(_fields).forEach((key) => {
164+
for (const key of _originalFieldsKey.keys()) {
160165
if (_isDirtyField(key)) {
161166
set(dirtyFields, key, true)
162167
} else {
163168
unset(dirtyFields, key)
164-
_fields[key].isDirty = false
169+
_getField(key).isDirty = false
165170
}
166-
})
171+
}
167172

168173
if (handleIsDirty) {
169174
_setFormState({
@@ -175,10 +180,14 @@ export function creatFormControl<
175180
}
176181

177182
const _handleDirtyField = (fieldName: FieldsKey) => {
178-
if (_fields[fieldName].isUnregistered) return
183+
const field = _getField(fieldName)
184+
185+
if (field.isUnregistered) {
186+
return
187+
}
179188

180189
const defaultVal = get(_defaultValues, fieldName as string)
181-
const val = _fields[fieldName].inputValue.value
190+
const val = field.inputValue.value
182191

183192
if (deepEqual(defaultVal, val)) {
184193
_setFields(fieldName, {
@@ -196,9 +205,9 @@ export function creatFormControl<
196205
fieldNames?: FieldsKey | FieldsKey[]
197206
) => {
198207
if (isUndefined(fieldNames)) {
199-
Object.keys(_fields).forEach((fieldName) => {
208+
for (const fieldName of _originalFieldsKey.keys()) {
200209
_handleDirtyField(fieldName)
201-
})
210+
}
202211
} else if (!isArray(fieldNames)) {
203212
fieldNames = [fieldNames]
204213

@@ -223,7 +232,7 @@ export function creatFormControl<
223232
fieldName: FieldsKey,
224233
isValidateAllFields = false
225234
) => {
226-
const field = _fields[fieldName]
235+
const field = _getField(fieldName)
227236

228237
if (isEmptyObject(_fields) || isNullOrUndefined(field)) {
229238
return
@@ -289,7 +298,7 @@ export function creatFormControl<
289298
if (
290299
isFunction(resolver) &&
291300
isEmptyObject(res) &&
292-
!isEmptyObject(_fields[fieldName].rule)
301+
!isEmptyObject(_getField(fieldName).rule)
293302
)
294303
res = await validateField(
295304
field,
@@ -317,7 +326,7 @@ export function creatFormControl<
317326

318327
const _validateAllFields = async () => {
319328
_setValidating(true)
320-
for (const fieldName of Object.keys(_fields))
329+
for (const fieldName of _originalFieldsKey.keys())
321330
await _validate(fieldName, true)
322331

323332
_setValidating(false)
@@ -354,13 +363,14 @@ export function creatFormControl<
354363
}
355364

356365
Object.entries(values).forEach(([key, val]) => {
357-
const el = _fields[key].el.value
366+
const field = _getField(key)
367+
const el = field.el.value
358368

359369
if (!keepStateOptions.keepDefaultValues) {
360370
_formState.defaultValues[key as keyof TFieldValues] = val
361371
}
362372
if (!keepStateOptions.keepValues) {
363-
_fields[key].inputValue.value = val
373+
field.inputValue.value = val
364374
}
365375
if (isRadioOrCheckboxInput(el)) {
366376
el.checked = val
@@ -418,8 +428,8 @@ export function creatFormControl<
418428
}
419429

420430
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
423433
}
424434

425435
await onSubmit(_fields as UnpackNestedValue<TFieldValues>, e)
@@ -439,7 +449,7 @@ export function creatFormControl<
439449
_setFormStateError(fieldName, {
440450
message: '',
441451
...error,
442-
el: _fields[fieldName].el,
452+
el: _getField(fieldName).el,
443453
} as FieldError)
444454

445455
_setFormState({
@@ -466,15 +476,29 @@ export function creatFormControl<
466476
}
467477

468478
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+
})
470494
}
471495

472496
const setValue: UseFormSetValue<TFieldValues, FieldsKey> = async (
473497
name,
474498
value,
475499
config = {}
476500
) => {
477-
if (isNullOrUndefined(_fields[name])) {
501+
if (isNullOrUndefined(_getField(name))) {
478502
warn(`setValue cannot set not exist field #${name as string}`)
479503
return
480504
}
@@ -487,9 +511,13 @@ export function creatFormControl<
487511

488512
_setFieldsValue(name, value)
489513

490-
if (config.shouldDirty) _handleAllDirtyFieldsOperate(name)
514+
if (config.shouldDirty) {
515+
_handleAllDirtyFieldsOperate(name)
516+
}
491517

492-
if (config.shouldValidate) await trigger(name)
518+
if (config.shouldValidate) {
519+
await trigger(name)
520+
}
493521
}
494522

495523
const setFocus: UseFormSetFocus<TFieldValues> = (name) =>
@@ -503,14 +531,14 @@ export function creatFormControl<
503531
const res: GetValuesReturn<FieldValues, FieldsKey> = {}
504532

505533
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+
}
509537
} else {
510538
if (!isArray(fieldNames)) fieldNames = [fieldNames]
511539

512540
fieldNames.forEach((name) => {
513-
set(res, name as string, _fields[name].inputValue.value)
541+
set(res, name as string, _getField(name).inputValue.value)
514542
})
515543
}
516544

@@ -532,9 +560,10 @@ export function creatFormControl<
532560
if (isUndefined(options)) {
533561
options = {}
534562
}
563+
_originalFieldsKey.add(fieldName)
535564

536565
let isModelValue = false
537-
let field = get(_fields, fieldName)
566+
let field = _getField(fieldName)
538567

539568
const { vModelBinding = 'modelValue' } = options
540569

@@ -557,23 +586,23 @@ export function creatFormControl<
557586
isUnregistered: false,
558587
el: ref(null),
559588
})
560-
field = get(_fields, fieldName)
589+
field = _getField(fieldName)
561590

562591
nextTick(() => {
563592
const el = field.el.value
564-
if (el instanceof HTMLElement && isRadioOrCheckboxInput(el)) {
593+
if (el instanceof HTMLInputElement && isRadioOrCheckboxInput(el)) {
565594
el.checked = defaultVal === '' ? false : defaultVal
566595
}
567596
})
568597
}
569598

570599
const addEventListenerToElement = () => {
571-
if (isFieldElement(field.el) || _fields[fieldName].isUnregistered) {
600+
if (isFieldElement(field.el) || field.isUnregistered) {
572601
return
573602
}
574603

575604
const el = getFormEl(field.el)
576-
_fields[fieldName].el.value = el
605+
field.el.value = el
577606

578607
if (isRadioOrCheckboxInput(el)) {
579608
set(_defaultValues, fieldName as string, !!defaultVal)
@@ -604,12 +633,12 @@ export function creatFormControl<
604633

605634
return {
606635
// avoid rebinding ref
607-
...(!isFieldElement(field.el) && { ref: _fields[fieldName].el }),
636+
...(!isFieldElement(field.el) && { ref: field.el }),
608637

609638
...(vModelBinding === 'modelValue' && {
610639
value: field.inputValue.value,
611640
onInput: (e) => {
612-
if (_fields[fieldName].isUnregistered) return
641+
if (field.isUnregistered) return
613642

614643
addEventListenerToElement()
615644
queueMicrotask(() => {
@@ -622,7 +651,7 @@ export function creatFormControl<
622651

623652
[vModelBinding]: field.inputValue.value,
624653
[`onUpdate:${vModelBinding}`]: (input: any) => {
625-
if (_fields[fieldName].isUnregistered) return
654+
if (field.isUnregistered) return
626655

627656
isModelValue = true
628657
addEventListenerToElement()
@@ -635,7 +664,7 @@ export function creatFormControl<
635664
fieldName,
636665
options = {}
637666
) => {
638-
if (isNullOrUndefined(_fields[fieldName])) {
667+
if (isNullOrUndefined(_getField(fieldName))) {
639668
warn(`cannot unregister not exist field #${fieldName as string}`)
640669
return
641670
}
@@ -662,11 +691,13 @@ export function creatFormControl<
662691
)
663692
}
664693

665-
set(_fields[fieldName as string], 'isUnregistered', true)
694+
_setFields(fieldName, {
695+
isUnregistered: true,
696+
})
666697
}
667698

668699
const isExistInErrors = (fieldName: keyof TFieldValues) =>
669-
Object.keys(_formState.errors).includes(fieldName as string)
700+
!isEmptyObject(getPath(fieldName as string, _formState.errors))
670701

671702
return {
672703
control: {

packages/core/src/utils/getPath.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import toPath from 'lodash.topath'
2+
import { isUndefined } from '.'
3+
4+
export function getPath(
5+
path: string,
6+
obj: Record<string, any>,
7+
endIndex?: number
8+
) {
9+
const paths = toPath(path)
10+
11+
let res = obj
12+
13+
for (const key of paths.slice(
14+
0,
15+
isUndefined(endIndex) ? paths.length : endIndex
16+
)) {
17+
res = res?.[key]
18+
if (!res) {
19+
return
20+
}
21+
}
22+
23+
return res
24+
}

0 commit comments

Comments
 (0)
0