react-hook-form 7.12.1-next.0 → 7.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +834 -809
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/getFieldsValues.d.ts +4 -0
- package/dist/logic/getProxyFormState.d.ts +2 -1
- package/dist/logic/getResolverOptions.d.ts +2 -2
- package/dist/logic/hasValidation.d.ts +0 -1
- package/dist/logic/shouldRenderFormState.d.ts +1 -1
- package/dist/logic/validateField.d.ts +1 -1
- package/dist/types/controller.d.ts +1 -1
- package/dist/types/fieldArray.d.ts +1 -0
- package/dist/types/fields.d.ts +1 -0
- package/dist/types/form.d.ts +20 -35
- package/dist/types/validator.d.ts +0 -1
- package/dist/useController.d.ts +1 -1
- package/dist/useFieldArray.d.ts +1 -1
- package/dist/useForm.d.ts +1 -1
- package/dist/useFormContext.d.ts +1 -1
- package/dist/useWatch.d.ts +0 -3
- package/dist/utils/isProxyEnabled.d.ts +2 -0
- package/package.json +4 -4
- package/dist/logic/createFormControl.d.ts +0 -2
- package/dist/logic/getFocusFieldName.d.ts +0 -3
- package/dist/logic/unsetEmptyArray.d.ts +0 -2
- package/dist/utils/live.d.ts +0 -3
- package/dist/utils/omitKeys.d.ts +0 -2
package/dist/index.esm.js
CHANGED
@@ -70,46 +70,50 @@ FormContext.displayName = 'RHFContext';
|
|
70
70
|
const useFormContext = () => React.useContext(FormContext);
|
71
71
|
const FormProvider = (props) => (React.createElement(FormContext.Provider, { value: omit(props, 'children') }, props.children));
|
72
72
|
|
73
|
-
var getProxyFormState = (formState,
|
74
|
-
|
75
|
-
|
76
|
-
if (prop in
|
77
|
-
if (
|
78
|
-
|
73
|
+
var getProxyFormState = (isProxyEnabled, formState, readFormStateRef, localReadFormStateRef, isRoot = true) => isProxyEnabled
|
74
|
+
? new Proxy(formState, {
|
75
|
+
get: (obj, prop) => {
|
76
|
+
if (prop in obj) {
|
77
|
+
if (readFormStateRef.current[prop] !== VALIDATION_MODE.all) {
|
78
|
+
readFormStateRef.current[prop] = isRoot
|
79
|
+
? VALIDATION_MODE.all
|
80
|
+
: true;
|
79
81
|
}
|
80
|
-
|
81
|
-
|
82
|
+
localReadFormStateRef &&
|
83
|
+
(localReadFormStateRef.current[prop] = true);
|
84
|
+
return obj[prop];
|
82
85
|
}
|
83
86
|
return undefined;
|
84
|
-
}
|
85
|
-
}
|
86
|
-
|
87
|
-
for (const key in formState) {
|
88
|
-
Object.defineProperty(result, key, {
|
89
|
-
get: createGetter(key),
|
90
|
-
});
|
91
|
-
}
|
92
|
-
return result;
|
93
|
-
};
|
87
|
+
},
|
88
|
+
})
|
89
|
+
: formState;
|
94
90
|
|
95
91
|
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
96
92
|
|
97
|
-
var shouldRenderFormState = (formStateData,
|
93
|
+
var shouldRenderFormState = (formStateData, readFormStateRef, isRoot) => {
|
98
94
|
const formState = omit(formStateData, 'name');
|
99
95
|
return (isEmptyObject(formState) ||
|
100
|
-
Object.keys(formState).length >= Object.keys(
|
101
|
-
Object.keys(formState).find((key) =>
|
102
|
-
(
|
96
|
+
Object.keys(formState).length >= Object.keys(readFormStateRef).length ||
|
97
|
+
Object.keys(formState).find((key) => readFormStateRef[key] ===
|
98
|
+
(isRoot ? VALIDATION_MODE.all : true)));
|
103
99
|
};
|
104
100
|
|
105
101
|
var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
|
106
102
|
|
103
|
+
var isWeb = typeof window !== 'undefined' &&
|
104
|
+
typeof window.HTMLElement !== 'undefined' &&
|
105
|
+
typeof document !== 'undefined';
|
106
|
+
|
107
|
+
const isProxyEnabled = isWeb ? 'Proxy' in window : typeof Proxy !== 'undefined';
|
108
|
+
|
107
109
|
function useFormState(props) {
|
110
|
+
const { control, name } = props || {};
|
108
111
|
const methods = useFormContext();
|
109
|
-
const {
|
112
|
+
const { formStateRef, subjectsRef, readFormStateRef } = control || methods.control;
|
110
113
|
const nameRef = React.useRef(name);
|
111
|
-
|
112
|
-
const
|
114
|
+
nameRef.current = name;
|
115
|
+
const [formState, updateFormState] = React.useState(formStateRef.current);
|
116
|
+
const readFormState = React.useRef({
|
113
117
|
isDirty: false,
|
114
118
|
dirtyFields: false,
|
115
119
|
touchedFields: false,
|
@@ -117,61 +121,64 @@ function useFormState(props) {
|
|
117
121
|
isValid: false,
|
118
122
|
errors: false,
|
119
123
|
});
|
120
|
-
nameRef.current = name;
|
121
124
|
React.useEffect(() => {
|
122
|
-
const formStateSubscription =
|
125
|
+
const formStateSubscription = subjectsRef.current.state.subscribe({
|
123
126
|
next: (formState) => (!nameRef.current ||
|
124
127
|
!formState.name ||
|
125
128
|
convertToArrayPayload(nameRef.current).includes(formState.name)) &&
|
126
|
-
shouldRenderFormState(formState,
|
127
|
-
updateFormState(Object.assign(Object.assign({},
|
129
|
+
shouldRenderFormState(formState, readFormState.current) &&
|
130
|
+
updateFormState(Object.assign(Object.assign({}, formStateRef.current), formState)),
|
128
131
|
});
|
129
|
-
disabled && formStateSubscription.unsubscribe();
|
130
132
|
return () => formStateSubscription.unsubscribe();
|
131
|
-
}, [
|
132
|
-
return getProxyFormState(formState,
|
133
|
+
}, []);
|
134
|
+
return getProxyFormState(isProxyEnabled, formState, readFormStateRef, readFormState, false);
|
133
135
|
}
|
134
136
|
|
135
|
-
function useController(
|
137
|
+
function useController({ name, rules, defaultValue, control, shouldUnregister, }) {
|
136
138
|
const methods = useFormContext();
|
137
|
-
const {
|
138
|
-
const
|
139
|
+
const { defaultValuesRef, register, fieldsRef, unregister, namesRef, subjectsRef, shouldUnmount, inFieldArrayActionRef, } = control || methods.control;
|
140
|
+
const field = get(fieldsRef.current, name);
|
141
|
+
const [value, setInputStateValue] = React.useState(field && field._f && !isUndefined(field._f.value)
|
142
|
+
? field._f.value
|
143
|
+
: isUndefined(get(defaultValuesRef.current, name))
|
144
|
+
? defaultValue
|
145
|
+
: get(defaultValuesRef.current, name));
|
146
|
+
const { onChange, onBlur, ref } = register(name, Object.assign(Object.assign({}, rules), { value }));
|
139
147
|
const formState = useFormState({
|
140
148
|
control: control || methods.control,
|
141
149
|
name,
|
142
150
|
});
|
143
|
-
|
151
|
+
function updateIsMounted(name, value) {
|
152
|
+
const field = get(fieldsRef.current, name);
|
153
|
+
if (field && field._f) {
|
154
|
+
field._f.mount = value;
|
155
|
+
}
|
156
|
+
}
|
144
157
|
React.useEffect(() => {
|
145
|
-
const controllerSubscription =
|
158
|
+
const controllerSubscription = subjectsRef.current.control.subscribe({
|
146
159
|
next: (data) => (!data.name || name === data.name) &&
|
147
160
|
setInputStateValue(get(data.values, name)),
|
148
161
|
});
|
149
|
-
|
150
|
-
if (field) {
|
151
|
-
field._f.mount = true;
|
152
|
-
}
|
162
|
+
updateIsMounted(name, true);
|
153
163
|
return () => {
|
154
164
|
controllerSubscription.unsubscribe();
|
155
|
-
const
|
156
|
-
if (isNameInFieldArray(
|
157
|
-
?
|
158
|
-
:
|
159
|
-
|
165
|
+
const shouldUnmountField = shouldUnmount || shouldUnregister;
|
166
|
+
if (isNameInFieldArray(namesRef.current.array, name)
|
167
|
+
? shouldUnmountField && !inFieldArrayActionRef.current
|
168
|
+
: shouldUnmountField) {
|
169
|
+
unregister(name);
|
160
170
|
}
|
161
171
|
else {
|
162
|
-
|
163
|
-
if (field) {
|
164
|
-
field._f.mount = false;
|
165
|
-
}
|
172
|
+
updateIsMounted(name, false);
|
166
173
|
}
|
167
174
|
};
|
168
|
-
}, [name
|
175
|
+
}, [name]);
|
169
176
|
return {
|
170
177
|
field: {
|
171
178
|
onChange: (event) => {
|
172
179
|
const value = getControllerValue(event);
|
173
180
|
setInputStateValue(value);
|
174
|
-
|
181
|
+
onChange({
|
175
182
|
target: {
|
176
183
|
value,
|
177
184
|
name: name,
|
@@ -180,7 +187,7 @@ function useController(props) {
|
|
180
187
|
});
|
181
188
|
},
|
182
189
|
onBlur: () => {
|
183
|
-
|
190
|
+
onBlur({
|
184
191
|
target: {
|
185
192
|
name: name,
|
186
193
|
},
|
@@ -190,7 +197,7 @@ function useController(props) {
|
|
190
197
|
name,
|
191
198
|
value,
|
192
199
|
ref: (elm) => elm &&
|
193
|
-
|
200
|
+
ref({
|
194
201
|
focus: () => elm.focus && elm.focus(),
|
195
202
|
setCustomValidity: (message) => elm.setCustomValidity(message),
|
196
203
|
reportValidity: () => elm.reportValidity(),
|
@@ -260,9 +267,27 @@ const focusFieldBy = (fields, callback, fieldsNames) => {
|
|
260
267
|
}
|
261
268
|
};
|
262
269
|
|
263
|
-
|
264
|
-
|
265
|
-
|
270
|
+
const getFieldsValues = (fieldsRef, output = {}) => {
|
271
|
+
for (const name in fieldsRef.current) {
|
272
|
+
const field = fieldsRef.current[name];
|
273
|
+
if (field && !isNullOrUndefined(output)) {
|
274
|
+
const _f = field._f;
|
275
|
+
const current = omit(field, '_f');
|
276
|
+
set(output, name, _f && _f.ref
|
277
|
+
? _f.ref.disabled || (_f.refs && _f.refs.every((ref) => ref.disabled))
|
278
|
+
? undefined
|
279
|
+
: _f.value
|
280
|
+
: Array.isArray(field)
|
281
|
+
? []
|
282
|
+
: {});
|
283
|
+
current &&
|
284
|
+
getFieldsValues({
|
285
|
+
current,
|
286
|
+
}, output[name]);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
return output;
|
290
|
+
};
|
266
291
|
|
267
292
|
var generateId = () => {
|
268
293
|
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
|
@@ -274,6 +299,80 @@ var generateId = () => {
|
|
274
299
|
|
275
300
|
var mapIds = (values = [], keyName) => values.map((value) => (Object.assign({ [keyName]: (value && value[keyName]) || generateId() }, value)));
|
276
301
|
|
302
|
+
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
303
|
+
|
304
|
+
function deepEqual(object1, object2, isErrorObject) {
|
305
|
+
if (isPrimitive(object1) ||
|
306
|
+
isPrimitive(object2) ||
|
307
|
+
isDateObject(object1) ||
|
308
|
+
isDateObject(object2)) {
|
309
|
+
return object1 === object2;
|
310
|
+
}
|
311
|
+
if (!React.isValidElement(object1)) {
|
312
|
+
const keys1 = Object.keys(object1);
|
313
|
+
const keys2 = Object.keys(object2);
|
314
|
+
if (keys1.length !== keys2.length) {
|
315
|
+
return false;
|
316
|
+
}
|
317
|
+
for (const key of keys1) {
|
318
|
+
const val1 = object1[key];
|
319
|
+
if (!(isErrorObject && key === 'ref')) {
|
320
|
+
const val2 = object2[key];
|
321
|
+
if ((isObject(val1) || Array.isArray(val1)) &&
|
322
|
+
(isObject(val2) || Array.isArray(val2))
|
323
|
+
? !deepEqual(val1, val2, isErrorObject)
|
324
|
+
: val1 !== val2) {
|
325
|
+
return false;
|
326
|
+
}
|
327
|
+
}
|
328
|
+
}
|
329
|
+
}
|
330
|
+
return true;
|
331
|
+
}
|
332
|
+
|
333
|
+
function deepMerge(target, source) {
|
334
|
+
if (isPrimitive(target) || isPrimitive(source)) {
|
335
|
+
return source;
|
336
|
+
}
|
337
|
+
for (const key in source) {
|
338
|
+
const targetValue = target[key];
|
339
|
+
const sourceValue = source[key];
|
340
|
+
try {
|
341
|
+
target[key] =
|
342
|
+
(isObject(targetValue) && isObject(sourceValue)) ||
|
343
|
+
(Array.isArray(targetValue) && Array.isArray(sourceValue))
|
344
|
+
? deepMerge(targetValue, sourceValue)
|
345
|
+
: sourceValue;
|
346
|
+
}
|
347
|
+
catch (_a) { }
|
348
|
+
}
|
349
|
+
return target;
|
350
|
+
}
|
351
|
+
|
352
|
+
function setDirtyFields(values, defaultValues, dirtyFields, parentNode, parentName) {
|
353
|
+
let index = -1;
|
354
|
+
while (++index < values.length) {
|
355
|
+
for (const key in values[index]) {
|
356
|
+
if (Array.isArray(values[index][key])) {
|
357
|
+
!dirtyFields[index] && (dirtyFields[index] = {});
|
358
|
+
dirtyFields[index][key] = [];
|
359
|
+
setDirtyFields(values[index][key], get(defaultValues[index] || {}, key, []), dirtyFields[index][key], dirtyFields[index], key);
|
360
|
+
}
|
361
|
+
else {
|
362
|
+
!isNullOrUndefined(defaultValues) &&
|
363
|
+
deepEqual(get(defaultValues[index] || {}, key), values[index][key])
|
364
|
+
? set(dirtyFields[index] || {}, key)
|
365
|
+
: (dirtyFields[index] = Object.assign(Object.assign({}, dirtyFields[index]), { [key]: true }));
|
366
|
+
}
|
367
|
+
}
|
368
|
+
parentNode &&
|
369
|
+
!dirtyFields.length &&
|
370
|
+
delete parentNode[parentName];
|
371
|
+
}
|
372
|
+
return dirtyFields;
|
373
|
+
}
|
374
|
+
var setFieldArrayDirtyFields = (values, defaultValues, dirtyFields) => deepMerge(setDirtyFields(values, defaultValues, dirtyFields.slice(0, values.length)), setDirtyFields(defaultValues, values, dirtyFields.slice(0, values.length)));
|
375
|
+
|
277
376
|
function append(data, value) {
|
278
377
|
return [...convertToArrayPayload(data), ...convertToArrayPayload(value)];
|
279
378
|
}
|
@@ -299,8 +398,6 @@ var moveArrayAt = (data, from, to) => {
|
|
299
398
|
return [];
|
300
399
|
};
|
301
400
|
|
302
|
-
var omitKey = (fields, keyName) => fields.map((field = {}) => omit(field, keyName));
|
303
|
-
|
304
401
|
function prepend(data, value) {
|
305
402
|
return [...convertToArrayPayload(value), ...convertToArrayPayload(data)];
|
306
403
|
}
|
@@ -363,247 +460,211 @@ function unset(object, path) {
|
|
363
460
|
return object;
|
364
461
|
}
|
365
462
|
|
366
|
-
const useFieldArray = (
|
463
|
+
const useFieldArray = ({ control, name, keyName = 'id', shouldUnregister, }) => {
|
367
464
|
const methods = useFormContext();
|
368
|
-
const
|
369
|
-
const
|
370
|
-
const
|
371
|
-
|
465
|
+
const focusNameRef = React.useRef('');
|
466
|
+
const isMountedRef = React.useRef(false);
|
467
|
+
const { getIsDirty, namesRef, fieldsRef, defaultValuesRef, formStateRef, subjectsRef, readFormStateRef, updateIsValid, fieldArrayDefaultValuesRef, unregister, shouldUnmount, inFieldArrayActionRef, setValues, register, } = control || methods.control;
|
468
|
+
const [fields, setFields] = React.useState(mapIds((get(fieldsRef.current, name) && isMountedRef.current
|
469
|
+
? get(getFieldsValues(fieldsRef), name)
|
470
|
+
: get(fieldArrayDefaultValuesRef.current, getNodeParentName(name))
|
471
|
+
? get(fieldArrayDefaultValuesRef.current, name)
|
472
|
+
: get(defaultValuesRef.current, name)) || [], keyName));
|
473
|
+
set(fieldArrayDefaultValuesRef.current, name, [...fields]);
|
474
|
+
namesRef.current.array.add(name);
|
475
|
+
const omitKey = (fields) => fields.map((field = {}) => omit(field, keyName));
|
476
|
+
const getCurrentFieldsValues = () => {
|
477
|
+
const values = get(getFieldsValues(fieldsRef), name, []);
|
478
|
+
return mapIds(get(fieldArrayDefaultValuesRef.current, name, []).map((item, index) => (Object.assign(Object.assign({}, item), values[index]))), keyName);
|
479
|
+
};
|
480
|
+
const getFocusFieldName = (index, options) => options && !options.shouldFocus
|
481
|
+
? options.focusName || `${name}.${options.focusIndex}.`
|
482
|
+
: `${name}.${index}.`;
|
483
|
+
const setFieldsAndNotify = (fieldsValues = []) => setFields(mapIds(fieldsValues, keyName));
|
484
|
+
const cleanup = (ref) => !compact(get(ref, name, [])).length && unset(ref, name);
|
485
|
+
const batchStateUpdate = (method, args, updatedFieldArrayValues = [], shouldSet = true) => {
|
486
|
+
inFieldArrayActionRef.current = true;
|
487
|
+
if (get(fieldsRef.current, name)) {
|
488
|
+
const output = method(get(fieldsRef.current, name), args.argA, args.argB);
|
489
|
+
shouldSet && set(fieldsRef.current, name, output);
|
490
|
+
}
|
491
|
+
if (Array.isArray(get(formStateRef.current.errors, name))) {
|
492
|
+
const output = method(get(formStateRef.current.errors, name), args.argA, args.argB);
|
493
|
+
shouldSet && set(formStateRef.current.errors, name, output);
|
494
|
+
cleanup(formStateRef.current.errors);
|
495
|
+
}
|
496
|
+
if (readFormStateRef.current.touchedFields &&
|
497
|
+
get(formStateRef.current.touchedFields, name)) {
|
498
|
+
const output = method(get(formStateRef.current.touchedFields, name), args.argA, args.argB);
|
499
|
+
shouldSet && set(formStateRef.current.touchedFields, name, output);
|
500
|
+
cleanup(formStateRef.current.touchedFields);
|
501
|
+
}
|
502
|
+
if (readFormStateRef.current.dirtyFields ||
|
503
|
+
readFormStateRef.current.isDirty) {
|
504
|
+
set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
|
505
|
+
updatedFieldArrayValues &&
|
506
|
+
set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
|
507
|
+
cleanup(formStateRef.current.dirtyFields);
|
508
|
+
}
|
509
|
+
subjectsRef.current.state.next({
|
510
|
+
dirtyFields: formStateRef.current
|
511
|
+
.dirtyFields,
|
512
|
+
isDirty: getIsDirty(name, omitKey(updatedFieldArrayValues)),
|
513
|
+
errors: formStateRef.current.errors,
|
514
|
+
isValid: formStateRef.current.isValid,
|
515
|
+
});
|
516
|
+
};
|
517
|
+
const registerFieldArray = (values, index = 0, parentName = '') => values.forEach((appendValueItem, valueIndex) => {
|
518
|
+
const rootName = `${parentName || name}.${parentName ? valueIndex : index + valueIndex}`;
|
519
|
+
isPrimitive(appendValueItem)
|
520
|
+
? register(rootName, {
|
521
|
+
value: appendValueItem,
|
522
|
+
})
|
523
|
+
: Object.entries(appendValueItem).forEach(([key, value]) => {
|
524
|
+
const inputName = rootName + '.' + key;
|
525
|
+
Array.isArray(value)
|
526
|
+
? registerFieldArray(value, valueIndex, inputName)
|
527
|
+
: register(inputName, { value });
|
528
|
+
});
|
529
|
+
});
|
372
530
|
const append$1 = (value, options) => {
|
373
531
|
const appendValue = convertToArrayPayload(value);
|
374
|
-
const updatedFieldArrayValues = append(
|
375
|
-
|
376
|
-
|
532
|
+
const updatedFieldArrayValues = append(getCurrentFieldsValues(), appendValue);
|
533
|
+
const currentIndex = updatedFieldArrayValues.length - appendValue.length;
|
534
|
+
setFieldsAndNotify(updatedFieldArrayValues);
|
535
|
+
batchStateUpdate(append, {
|
377
536
|
argA: fillEmptyArray(value),
|
378
537
|
}, updatedFieldArrayValues, false);
|
379
|
-
|
538
|
+
registerFieldArray(appendValue, currentIndex);
|
539
|
+
focusNameRef.current = getFocusFieldName(currentIndex, options);
|
380
540
|
};
|
381
541
|
const prepend$1 = (value, options) => {
|
382
|
-
const
|
383
|
-
|
384
|
-
|
542
|
+
const prependValue = convertToArrayPayload(value);
|
543
|
+
const updatedFieldArrayValues = prepend(getCurrentFieldsValues(), prependValue);
|
544
|
+
setFieldsAndNotify(updatedFieldArrayValues);
|
545
|
+
batchStateUpdate(prepend, {
|
385
546
|
argA: fillEmptyArray(value),
|
386
547
|
}, updatedFieldArrayValues);
|
387
|
-
|
548
|
+
registerFieldArray(prependValue);
|
549
|
+
focusNameRef.current = getFocusFieldName(0, options);
|
388
550
|
};
|
389
551
|
const remove = (index) => {
|
390
|
-
const updatedFieldArrayValues = removeArrayAt(
|
391
|
-
|
392
|
-
|
552
|
+
const updatedFieldArrayValues = removeArrayAt(getCurrentFieldsValues(), index);
|
553
|
+
setFieldsAndNotify(updatedFieldArrayValues);
|
554
|
+
batchStateUpdate(removeArrayAt, {
|
393
555
|
argA: index,
|
394
556
|
}, updatedFieldArrayValues);
|
395
557
|
};
|
396
558
|
const insert$1 = (index, value, options) => {
|
397
|
-
const
|
398
|
-
|
399
|
-
|
559
|
+
const insertValue = convertToArrayPayload(value);
|
560
|
+
const updatedFieldArrayValues = insert(getCurrentFieldsValues(), index, insertValue);
|
561
|
+
setFieldsAndNotify(updatedFieldArrayValues);
|
562
|
+
batchStateUpdate(insert, {
|
400
563
|
argA: index,
|
401
564
|
argB: fillEmptyArray(value),
|
402
565
|
}, updatedFieldArrayValues);
|
403
|
-
|
566
|
+
registerFieldArray(insertValue, index);
|
567
|
+
focusNameRef.current = getFocusFieldName(index, options);
|
404
568
|
};
|
405
569
|
const swap = (indexA, indexB) => {
|
406
|
-
const fieldValues =
|
570
|
+
const fieldValues = getCurrentFieldsValues();
|
407
571
|
swapArrayAt(fieldValues, indexA, indexB);
|
408
|
-
|
572
|
+
batchStateUpdate(swapArrayAt, {
|
409
573
|
argA: indexA,
|
410
574
|
argB: indexB,
|
411
575
|
}, fieldValues, false);
|
412
|
-
|
576
|
+
setFieldsAndNotify(fieldValues);
|
413
577
|
};
|
414
578
|
const move = (from, to) => {
|
415
|
-
const fieldValues =
|
579
|
+
const fieldValues = getCurrentFieldsValues();
|
416
580
|
moveArrayAt(fieldValues, from, to);
|
417
|
-
|
418
|
-
|
581
|
+
setFieldsAndNotify(fieldValues);
|
582
|
+
batchStateUpdate(moveArrayAt, {
|
419
583
|
argA: from,
|
420
584
|
argB: to,
|
421
585
|
}, fieldValues, false);
|
422
586
|
};
|
423
587
|
const update = (index, value) => {
|
424
|
-
|
425
|
-
shouldValidate: !!
|
426
|
-
shouldDirty: !!(
|
588
|
+
setValues((name + '.' + index), value, {
|
589
|
+
shouldValidate: !!readFormStateRef.current.isValid,
|
590
|
+
shouldDirty: !!(readFormStateRef.current.dirtyFields ||
|
591
|
+
readFormStateRef.current.isDirty),
|
427
592
|
});
|
428
|
-
const fieldValues =
|
593
|
+
const fieldValues = getCurrentFieldsValues();
|
429
594
|
fieldValues[index] = value;
|
430
|
-
|
595
|
+
setFieldsAndNotify(fieldValues);
|
431
596
|
};
|
432
597
|
React.useEffect(() => {
|
433
|
-
|
434
|
-
if (
|
435
|
-
|
598
|
+
inFieldArrayActionRef.current = false;
|
599
|
+
if (namesRef.current.watchAll) {
|
600
|
+
subjectsRef.current.state.next({});
|
436
601
|
}
|
437
602
|
else {
|
438
|
-
for (const watchField of
|
603
|
+
for (const watchField of namesRef.current.watch) {
|
439
604
|
if (name.startsWith(watchField)) {
|
440
|
-
|
605
|
+
subjectsRef.current.state.next({});
|
441
606
|
break;
|
442
607
|
}
|
443
608
|
}
|
444
609
|
}
|
445
|
-
|
610
|
+
subjectsRef.current.watch.next({
|
446
611
|
name,
|
447
|
-
values:
|
612
|
+
values: getFieldsValues(fieldsRef),
|
448
613
|
});
|
449
|
-
|
450
|
-
focusFieldBy(
|
451
|
-
|
452
|
-
|
614
|
+
focusNameRef.current &&
|
615
|
+
focusFieldBy(fieldsRef.current, (key) => key.startsWith(focusNameRef.current));
|
616
|
+
focusNameRef.current = '';
|
617
|
+
subjectsRef.current.array.next({
|
453
618
|
name,
|
454
|
-
values: omitKey([...fields]
|
619
|
+
values: omitKey([...fields]),
|
455
620
|
});
|
456
|
-
|
457
|
-
}, [fields, name
|
621
|
+
readFormStateRef.current.isValid && updateIsValid();
|
622
|
+
}, [fields, name]);
|
458
623
|
React.useEffect(() => {
|
459
|
-
const fieldArraySubscription =
|
460
|
-
next(
|
461
|
-
if (
|
462
|
-
unset(
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
setFields(mapIds(get(control._formValues, name), keyName));
|
624
|
+
const fieldArraySubscription = subjectsRef.current.array.subscribe({
|
625
|
+
next({ name: inputFieldArrayName, values, isReset }) {
|
626
|
+
if (isReset) {
|
627
|
+
unset(fieldsRef.current, inputFieldArrayName || name);
|
628
|
+
inputFieldArrayName
|
629
|
+
? set(fieldArrayDefaultValuesRef.current, inputFieldArrayName, values)
|
630
|
+
: (fieldArrayDefaultValuesRef.current = values);
|
631
|
+
setFieldsAndNotify(get(fieldArrayDefaultValuesRef.current, name));
|
468
632
|
}
|
469
633
|
},
|
470
634
|
});
|
471
|
-
!get(
|
635
|
+
!get(fieldsRef.current, name) && set(fieldsRef.current, name, []);
|
636
|
+
isMountedRef.current = true;
|
472
637
|
return () => {
|
473
638
|
fieldArraySubscription.unsubscribe();
|
474
|
-
if (
|
475
|
-
|
476
|
-
unset(
|
639
|
+
if (shouldUnmount || shouldUnregister) {
|
640
|
+
unregister(name);
|
641
|
+
unset(fieldArrayDefaultValuesRef.current, name);
|
477
642
|
}
|
478
643
|
else {
|
479
|
-
const fieldArrayValues = get(
|
480
|
-
fieldArrayValues &&
|
644
|
+
const fieldArrayValues = get(getFieldsValues(fieldsRef), name);
|
645
|
+
fieldArrayValues &&
|
646
|
+
set(fieldArrayDefaultValuesRef.current, name, fieldArrayValues);
|
481
647
|
}
|
482
648
|
};
|
483
|
-
}, [
|
649
|
+
}, []);
|
484
650
|
return {
|
485
|
-
swap: React.useCallback(swap, [name
|
486
|
-
move: React.useCallback(move, [name
|
487
|
-
prepend: React.useCallback(prepend$1, [name
|
488
|
-
append: React.useCallback(append$1, [name
|
489
|
-
remove: React.useCallback(remove, [name
|
490
|
-
insert: React.useCallback(insert$1, [name
|
491
|
-
update: React.useCallback(update, [name
|
651
|
+
swap: React.useCallback(swap, [name]),
|
652
|
+
move: React.useCallback(move, [name]),
|
653
|
+
prepend: React.useCallback(prepend$1, [name]),
|
654
|
+
append: React.useCallback(append$1, [name]),
|
655
|
+
remove: React.useCallback(remove, [name]),
|
656
|
+
insert: React.useCallback(insert$1, [name]),
|
657
|
+
update: React.useCallback(update, [name]),
|
492
658
|
fields: fields,
|
493
659
|
};
|
494
660
|
};
|
495
661
|
|
496
|
-
var debounce = (callback, wait) => {
|
497
|
-
let timer = 0;
|
498
|
-
return (...args) => {
|
499
|
-
clearTimeout(timer);
|
500
|
-
timer = setTimeout(() => callback(...args), wait);
|
501
|
-
};
|
502
|
-
};
|
503
|
-
|
504
|
-
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
505
|
-
|
506
|
-
function deepEqual(object1, object2, isErrorObject) {
|
507
|
-
if (isPrimitive(object1) ||
|
508
|
-
isPrimitive(object2) ||
|
509
|
-
isDateObject(object1) ||
|
510
|
-
isDateObject(object2)) {
|
511
|
-
return object1 === object2;
|
512
|
-
}
|
513
|
-
if (!React.isValidElement(object1)) {
|
514
|
-
const keys1 = Object.keys(object1);
|
515
|
-
const keys2 = Object.keys(object2);
|
516
|
-
if (keys1.length !== keys2.length) {
|
517
|
-
return false;
|
518
|
-
}
|
519
|
-
for (const key of keys1) {
|
520
|
-
const val1 = object1[key];
|
521
|
-
if (!(isErrorObject && key === 'ref')) {
|
522
|
-
const val2 = object2[key];
|
523
|
-
if ((isObject(val1) || Array.isArray(val1)) &&
|
524
|
-
(isObject(val2) || Array.isArray(val2))
|
525
|
-
? !deepEqual(val1, val2, isErrorObject)
|
526
|
-
: val1 !== val2) {
|
527
|
-
return false;
|
528
|
-
}
|
529
|
-
}
|
530
|
-
}
|
531
|
-
}
|
532
|
-
return true;
|
533
|
-
}
|
534
|
-
|
535
|
-
var getValidationModes = (mode) => ({
|
536
|
-
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
|
537
|
-
isOnBlur: mode === VALIDATION_MODE.onBlur,
|
538
|
-
isOnChange: mode === VALIDATION_MODE.onChange,
|
539
|
-
isOnAll: mode === VALIDATION_MODE.all,
|
540
|
-
isOnTouch: mode === VALIDATION_MODE.onTouched,
|
541
|
-
});
|
542
|
-
|
543
662
|
var isFileInput = (element) => element.type === 'file';
|
544
663
|
|
545
|
-
var isFunction = (value) => typeof value === 'function';
|
546
|
-
|
547
|
-
var isHTMLElement = (value) => value instanceof HTMLElement;
|
548
|
-
|
549
664
|
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
550
665
|
|
551
666
|
var isRadioInput = (element) => element.type === 'radio';
|
552
667
|
|
553
|
-
var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
554
|
-
|
555
|
-
var isString = (value) => typeof value === 'string';
|
556
|
-
|
557
|
-
var isWeb = typeof window !== 'undefined' &&
|
558
|
-
typeof window.HTMLElement !== 'undefined' &&
|
559
|
-
typeof document !== 'undefined';
|
560
|
-
|
561
|
-
class Subscription {
|
562
|
-
constructor() {
|
563
|
-
this.tearDowns = [];
|
564
|
-
}
|
565
|
-
add(tearDown) {
|
566
|
-
this.tearDowns.push(tearDown);
|
567
|
-
}
|
568
|
-
unsubscribe() {
|
569
|
-
for (const teardown of this.tearDowns) {
|
570
|
-
teardown();
|
571
|
-
}
|
572
|
-
this.tearDowns = [];
|
573
|
-
}
|
574
|
-
}
|
575
|
-
class Subscriber {
|
576
|
-
constructor(observer, subscription) {
|
577
|
-
this.observer = observer;
|
578
|
-
this.closed = false;
|
579
|
-
subscription.add(() => (this.closed = true));
|
580
|
-
}
|
581
|
-
next(value) {
|
582
|
-
if (!this.closed) {
|
583
|
-
this.observer.next(value);
|
584
|
-
}
|
585
|
-
}
|
586
|
-
}
|
587
|
-
class Subject {
|
588
|
-
constructor() {
|
589
|
-
this.observers = [];
|
590
|
-
}
|
591
|
-
next(value) {
|
592
|
-
for (const observer of this.observers) {
|
593
|
-
observer.next(value);
|
594
|
-
}
|
595
|
-
}
|
596
|
-
subscribe(observer) {
|
597
|
-
const subscription = new Subscription();
|
598
|
-
const subscriber = new Subscriber(observer, subscription);
|
599
|
-
this.observers.push(subscriber);
|
600
|
-
return subscription;
|
601
|
-
}
|
602
|
-
unsubscribe() {
|
603
|
-
this.observers = [];
|
604
|
-
}
|
605
|
-
}
|
606
|
-
|
607
668
|
const defaultResult = {
|
608
669
|
value: false,
|
609
670
|
isValid: false,
|
@@ -661,7 +722,7 @@ var getRadioValue = (options) => Array.isArray(options)
|
|
661
722
|
function getFieldValue(field) {
|
662
723
|
if (field && field._f) {
|
663
724
|
const ref = field._f.ref;
|
664
|
-
if (
|
725
|
+
if (ref.disabled) {
|
665
726
|
return;
|
666
727
|
}
|
667
728
|
if (isFileInput(ref)) {
|
@@ -680,10 +741,10 @@ function getFieldValue(field) {
|
|
680
741
|
}
|
681
742
|
}
|
682
743
|
|
683
|
-
var getResolverOptions = (fieldsNames,
|
744
|
+
var getResolverOptions = (fieldsNames, fieldsRefs, criteriaMode, shouldUseNativeValidation) => {
|
684
745
|
const fields = {};
|
685
746
|
for (const name of fieldsNames) {
|
686
|
-
const field = get(
|
747
|
+
const field = get(fieldsRefs, name);
|
687
748
|
field && set(fields, name, field._f);
|
688
749
|
}
|
689
750
|
return {
|
@@ -704,49 +765,6 @@ var hasValidation = (options, mounted) => mounted &&
|
|
704
765
|
options.pattern ||
|
705
766
|
options.validate);
|
706
767
|
|
707
|
-
function deepMerge(target, source) {
|
708
|
-
if (isPrimitive(target) || isPrimitive(source)) {
|
709
|
-
return source;
|
710
|
-
}
|
711
|
-
for (const key in source) {
|
712
|
-
const targetValue = target[key];
|
713
|
-
const sourceValue = source[key];
|
714
|
-
try {
|
715
|
-
target[key] =
|
716
|
-
(isObject(targetValue) && isObject(sourceValue)) ||
|
717
|
-
(Array.isArray(targetValue) && Array.isArray(sourceValue))
|
718
|
-
? deepMerge(targetValue, sourceValue)
|
719
|
-
: sourceValue;
|
720
|
-
}
|
721
|
-
catch (_a) { }
|
722
|
-
}
|
723
|
-
return target;
|
724
|
-
}
|
725
|
-
|
726
|
-
function setDirtyFields(values, defaultValues, dirtyFields, parentNode, parentName) {
|
727
|
-
let index = -1;
|
728
|
-
while (++index < values.length) {
|
729
|
-
for (const key in values[index]) {
|
730
|
-
if (Array.isArray(values[index][key])) {
|
731
|
-
!dirtyFields[index] && (dirtyFields[index] = {});
|
732
|
-
dirtyFields[index][key] = [];
|
733
|
-
setDirtyFields(values[index][key], get(defaultValues[index] || {}, key, []), dirtyFields[index][key], dirtyFields[index], key);
|
734
|
-
}
|
735
|
-
else {
|
736
|
-
!isNullOrUndefined(defaultValues) &&
|
737
|
-
deepEqual(get(defaultValues[index] || {}, key), values[index][key])
|
738
|
-
? set(dirtyFields[index] || {}, key)
|
739
|
-
: (dirtyFields[index] = Object.assign(Object.assign({}, dirtyFields[index]), { [key]: true }));
|
740
|
-
}
|
741
|
-
}
|
742
|
-
parentNode &&
|
743
|
-
!dirtyFields.length &&
|
744
|
-
delete parentNode[parentName];
|
745
|
-
}
|
746
|
-
return dirtyFields;
|
747
|
-
}
|
748
|
-
var setFieldArrayDirtyFields = (values, defaultValues, dirtyFields) => deepMerge(setDirtyFields(values, defaultValues, dirtyFields.slice(0, values.length)), setDirtyFields(defaultValues, values, dirtyFields.slice(0, values.length)));
|
749
|
-
|
750
768
|
var skipValidation = ({ isOnBlur, isOnChange, isOnTouch, isTouched, isReValidateOnBlur, isReValidateOnChange, isBlurEvent, isSubmitted, isOnAll, }) => {
|
751
769
|
if (isOnAll) {
|
752
770
|
return false;
|
@@ -763,7 +781,9 @@ var skipValidation = ({ isOnBlur, isOnChange, isOnTouch, isTouched, isReValidate
|
|
763
781
|
return true;
|
764
782
|
};
|
765
783
|
|
766
|
-
var
|
784
|
+
var isFunction = (value) => typeof value === 'function';
|
785
|
+
|
786
|
+
var isString = (value) => typeof value === 'string';
|
767
787
|
|
768
788
|
var isMessage = (value) => isString(value) || React.isValidElement(value);
|
769
789
|
|
@@ -788,8 +808,7 @@ var getValueAndMessage = (validationData) => isObject(validationData) && !isRege
|
|
788
808
|
message: '',
|
789
809
|
};
|
790
810
|
|
791
|
-
var validateField = async (
|
792
|
-
const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f;
|
811
|
+
var validateField = async ({ _f: { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, value: inputValue, valueAsNumber, mount, }, }, validateAllFieldCriteria, shouldUseNativeValidation) => {
|
793
812
|
if (!mount) {
|
794
813
|
return {};
|
795
814
|
}
|
@@ -925,16 +944,75 @@ var validateField = async (field, inputValue, validateAllFieldCriteria, shouldUs
|
|
925
944
|
return error;
|
926
945
|
};
|
927
946
|
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
947
|
+
var debounce = (callback, wait) => {
|
948
|
+
let timer = 0;
|
949
|
+
return (...args) => {
|
950
|
+
clearTimeout(timer);
|
951
|
+
timer = setTimeout(() => callback(...args), wait);
|
952
|
+
};
|
953
|
+
};
|
954
|
+
|
955
|
+
var getValidationModes = (mode) => ({
|
956
|
+
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
|
957
|
+
isOnBlur: mode === VALIDATION_MODE.onBlur,
|
958
|
+
isOnChange: mode === VALIDATION_MODE.onChange,
|
959
|
+
isOnAll: mode === VALIDATION_MODE.all,
|
960
|
+
isOnTouch: mode === VALIDATION_MODE.onTouched,
|
961
|
+
});
|
962
|
+
|
963
|
+
var isHTMLElement = (value) => value instanceof HTMLElement;
|
964
|
+
|
965
|
+
var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
966
|
+
|
967
|
+
class Subscription {
|
968
|
+
constructor() {
|
969
|
+
this.tearDowns = [];
|
970
|
+
}
|
971
|
+
add(tearDown) {
|
972
|
+
this.tearDowns.push(tearDown);
|
973
|
+
}
|
974
|
+
unsubscribe() {
|
975
|
+
for (const teardown of this.tearDowns) {
|
976
|
+
teardown();
|
977
|
+
}
|
978
|
+
this.tearDowns = [];
|
979
|
+
}
|
980
|
+
}
|
981
|
+
class Subscriber {
|
982
|
+
constructor(observer, subscription) {
|
983
|
+
this.observer = observer;
|
984
|
+
this.closed = false;
|
985
|
+
subscription.add(() => (this.closed = true));
|
986
|
+
}
|
987
|
+
next(value) {
|
988
|
+
if (!this.closed) {
|
989
|
+
this.observer.next(value);
|
990
|
+
}
|
991
|
+
}
|
992
|
+
}
|
993
|
+
class Subject {
|
994
|
+
constructor() {
|
995
|
+
this.observers = [];
|
996
|
+
}
|
997
|
+
next(value) {
|
998
|
+
for (const observer of this.observers) {
|
999
|
+
observer.next(value);
|
1000
|
+
}
|
1001
|
+
}
|
1002
|
+
subscribe(observer) {
|
1003
|
+
const subscription = new Subscription();
|
1004
|
+
const subscriber = new Subscriber(observer, subscription);
|
1005
|
+
this.observers.push(subscriber);
|
1006
|
+
return subscription;
|
1007
|
+
}
|
1008
|
+
unsubscribe() {
|
1009
|
+
this.observers = [];
|
1010
|
+
}
|
1011
|
+
}
|
1012
|
+
|
933
1013
|
const isWindowUndefined = typeof window === 'undefined';
|
934
|
-
function
|
935
|
-
|
936
|
-
let _delayCallback;
|
937
|
-
let _formState = {
|
1014
|
+
function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_MODE.onChange, resolver, context, defaultValues = {}, shouldFocusError = true, delayError, shouldUseNativeValidation, shouldUnregister, criteriaMode, } = {}) {
|
1015
|
+
const [formState, updateFormState] = React.useState({
|
938
1016
|
isDirty: false,
|
939
1017
|
isValidating: false,
|
940
1018
|
dirtyFields: {},
|
@@ -945,172 +1023,201 @@ function createFormControl(props = {}) {
|
|
945
1023
|
isSubmitSuccessful: false,
|
946
1024
|
isValid: false,
|
947
1025
|
errors: {},
|
948
|
-
};
|
949
|
-
const
|
950
|
-
isDirty:
|
951
|
-
dirtyFields:
|
952
|
-
touchedFields:
|
953
|
-
isValidating:
|
954
|
-
isValid:
|
955
|
-
errors:
|
956
|
-
};
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
const
|
1026
|
+
});
|
1027
|
+
const readFormStateRef = React.useRef({
|
1028
|
+
isDirty: !isProxyEnabled,
|
1029
|
+
dirtyFields: !isProxyEnabled,
|
1030
|
+
touchedFields: !isProxyEnabled,
|
1031
|
+
isValidating: !isProxyEnabled,
|
1032
|
+
isValid: !isProxyEnabled,
|
1033
|
+
errors: !isProxyEnabled,
|
1034
|
+
});
|
1035
|
+
const resolverRef = React.useRef(resolver);
|
1036
|
+
const formStateRef = React.useRef(formState);
|
1037
|
+
const fieldsRef = React.useRef({});
|
1038
|
+
const defaultValuesRef = React.useRef(defaultValues);
|
1039
|
+
const fieldArrayDefaultValuesRef = React.useRef({});
|
1040
|
+
const contextRef = React.useRef(context);
|
1041
|
+
const inFieldArrayActionRef = React.useRef(false);
|
1042
|
+
const isMountedRef = React.useRef(false);
|
1043
|
+
const _delayCallback = React.useRef();
|
1044
|
+
const subjectsRef = React.useRef({
|
963
1045
|
watch: new Subject(),
|
964
1046
|
control: new Subject(),
|
965
1047
|
array: new Subject(),
|
966
1048
|
state: new Subject(),
|
967
|
-
};
|
968
|
-
|
1049
|
+
});
|
1050
|
+
const namesRef = React.useRef({
|
969
1051
|
mount: new Set(),
|
970
1052
|
unMount: new Set(),
|
971
1053
|
array: new Set(),
|
972
1054
|
watch: new Set(),
|
973
1055
|
watchAll: false,
|
1056
|
+
});
|
1057
|
+
const validationMode = getValidationModes(mode);
|
1058
|
+
const isValidateAllFieldCriteria = criteriaMode === VALIDATION_MODE.all;
|
1059
|
+
resolverRef.current = resolver;
|
1060
|
+
contextRef.current = context;
|
1061
|
+
const isFieldWatched = (name) => namesRef.current.watchAll ||
|
1062
|
+
namesRef.current.watch.has(name) ||
|
1063
|
+
namesRef.current.watch.has((name.match(/\w+/) || [])[0]);
|
1064
|
+
const updateErrorState = (name, error) => {
|
1065
|
+
set(formStateRef.current.errors, name, error);
|
1066
|
+
subjectsRef.current.state.next({
|
1067
|
+
errors: formStateRef.current.errors,
|
1068
|
+
});
|
974
1069
|
};
|
975
|
-
const
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
_names.watch.has((name.match(/\w+/) || [])[0]);
|
980
|
-
const shouldRenderBaseOnError = async (shouldSkipRender, name, error, fieldState, isValidFromResolver, isWatched) => {
|
981
|
-
const previousError = get(_formState.errors, name);
|
982
|
-
const isValid = _proxyFormState.isValid
|
983
|
-
? formOptions.resolver
|
1070
|
+
const shouldRenderBaseOnError = React.useCallback(async (shouldSkipRender, name, error, fieldState, isValidFromResolver, isWatched) => {
|
1071
|
+
const previousError = get(formStateRef.current.errors, name);
|
1072
|
+
const isValid = readFormStateRef.current.isValid
|
1073
|
+
? resolver
|
984
1074
|
? isValidFromResolver
|
985
|
-
: await validateForm(
|
1075
|
+
: await validateForm(fieldsRef.current, true)
|
986
1076
|
: false;
|
987
|
-
error
|
988
|
-
|
989
|
-
|
1077
|
+
if (delayError && error) {
|
1078
|
+
_delayCallback.current =
|
1079
|
+
_delayCallback.current || debounce(updateErrorState, delayError);
|
1080
|
+
_delayCallback.current(name, error);
|
1081
|
+
}
|
1082
|
+
else {
|
1083
|
+
error
|
1084
|
+
? set(formStateRef.current.errors, name, error)
|
1085
|
+
: unset(formStateRef.current.errors, name);
|
1086
|
+
}
|
990
1087
|
if ((isWatched ||
|
991
1088
|
(error ? !deepEqual(previousError, error, true) : previousError) ||
|
992
1089
|
!isEmptyObject(fieldState) ||
|
993
|
-
|
1090
|
+
formStateRef.current.isValid !== isValid) &&
|
994
1091
|
!shouldSkipRender) {
|
995
|
-
const updatedFormState = Object.assign(Object.assign({}, fieldState), { isValid: !!isValid, errors:
|
996
|
-
|
997
|
-
|
1092
|
+
const updatedFormState = Object.assign(Object.assign({}, fieldState), { isValid: !!isValid, errors: formStateRef.current.errors, name });
|
1093
|
+
formStateRef.current = Object.assign(Object.assign({}, formStateRef.current), updatedFormState);
|
1094
|
+
subjectsRef.current.state.next(isWatched ? { name } : updatedFormState);
|
998
1095
|
}
|
999
|
-
|
1096
|
+
subjectsRef.current.state.next({
|
1000
1097
|
isValidating: false,
|
1001
1098
|
});
|
1002
|
-
};
|
1003
|
-
const setFieldValue = (name,
|
1099
|
+
}, []);
|
1100
|
+
const setFieldValue = React.useCallback((name, rawValue, options = {}, shouldRender, shouldRegister) => {
|
1004
1101
|
shouldRegister && register(name);
|
1005
|
-
const field = get(
|
1102
|
+
const field = get(fieldsRef.current, name);
|
1006
1103
|
if (field) {
|
1007
1104
|
const _f = field._f;
|
1008
1105
|
if (_f) {
|
1009
|
-
|
1010
|
-
const fieldValue = isWeb && isHTMLElement(_f.ref) && isNullOrUndefined(value)
|
1106
|
+
const value = isWeb && isHTMLElement(_f.ref) && isNullOrUndefined(rawValue)
|
1011
1107
|
? ''
|
1012
|
-
:
|
1013
|
-
|
1014
|
-
|
1108
|
+
: rawValue;
|
1109
|
+
_f.value = getFieldValueAs(rawValue, _f);
|
1110
|
+
if (isRadioInput(_f.ref)) {
|
1111
|
+
(_f.refs || []).forEach((radioRef) => (radioRef.checked = radioRef.value === value));
|
1112
|
+
}
|
1113
|
+
else if (isFileInput(_f.ref) && !isString(value)) {
|
1114
|
+
_f.ref.files = value;
|
1015
1115
|
}
|
1016
1116
|
else if (isMultipleSelect(_f.ref)) {
|
1017
|
-
[..._f.ref.options].forEach((selectRef) => (selectRef.selected =
|
1117
|
+
[..._f.ref.options].forEach((selectRef) => (selectRef.selected = value.includes(selectRef.value)));
|
1018
1118
|
}
|
1019
|
-
else if (_f.refs) {
|
1020
|
-
|
1021
|
-
_f.refs.
|
1022
|
-
?
|
1023
|
-
|
1024
|
-
|
1025
|
-
: (_f.refs[0].checked = !!fieldValue);
|
1026
|
-
}
|
1027
|
-
else {
|
1028
|
-
_f.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
|
1029
|
-
}
|
1119
|
+
else if (isCheckBoxInput(_f.ref) && _f.refs) {
|
1120
|
+
_f.refs.length > 1
|
1121
|
+
? _f.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(value)
|
1122
|
+
? !!value.find((data) => data === checkboxRef.value)
|
1123
|
+
: value === checkboxRef.value))
|
1124
|
+
: (_f.refs[0].checked = !!value);
|
1030
1125
|
}
|
1031
1126
|
else {
|
1032
|
-
_f.ref.value =
|
1127
|
+
_f.ref.value = value;
|
1033
1128
|
}
|
1034
1129
|
if (shouldRender) {
|
1035
|
-
|
1036
|
-
|
1130
|
+
const values = getFieldsValues(fieldsRef);
|
1131
|
+
set(values, name, rawValue);
|
1132
|
+
subjectsRef.current.control.next({
|
1133
|
+
values: Object.assign(Object.assign({}, defaultValuesRef.current), values),
|
1037
1134
|
name,
|
1038
1135
|
});
|
1039
1136
|
}
|
1040
1137
|
(options.shouldDirty || options.shouldTouch) &&
|
1041
|
-
updateTouchAndDirtyState(name,
|
1138
|
+
updateTouchAndDirtyState(name, value, options.shouldTouch);
|
1042
1139
|
options.shouldValidate && trigger(name);
|
1043
1140
|
}
|
1141
|
+
else {
|
1142
|
+
field._f = {
|
1143
|
+
ref: {
|
1144
|
+
name,
|
1145
|
+
value: rawValue,
|
1146
|
+
},
|
1147
|
+
value: rawValue,
|
1148
|
+
};
|
1149
|
+
}
|
1044
1150
|
}
|
1045
|
-
};
|
1046
|
-
const
|
1151
|
+
}, []);
|
1152
|
+
const getIsDirty = React.useCallback((name, data) => {
|
1153
|
+
const formValues = getFieldsValues(fieldsRef);
|
1154
|
+
name && data && set(formValues, name, data);
|
1155
|
+
return !deepEqual(formValues, defaultValuesRef.current);
|
1156
|
+
}, []);
|
1157
|
+
const updateTouchAndDirtyState = React.useCallback((name, inputValue, isCurrentTouched, shouldRender = true) => {
|
1047
1158
|
const state = {
|
1048
1159
|
name,
|
1049
1160
|
};
|
1050
1161
|
let isChanged = false;
|
1051
|
-
if (
|
1052
|
-
const previousIsDirty =
|
1053
|
-
|
1054
|
-
state.isDirty =
|
1162
|
+
if (readFormStateRef.current.isDirty) {
|
1163
|
+
const previousIsDirty = formStateRef.current.isDirty;
|
1164
|
+
formStateRef.current.isDirty = getIsDirty();
|
1165
|
+
state.isDirty = formStateRef.current.isDirty;
|
1055
1166
|
isChanged = previousIsDirty !== state.isDirty;
|
1056
1167
|
}
|
1057
|
-
if (
|
1058
|
-
const isPreviousFieldDirty = get(
|
1059
|
-
const isCurrentFieldDirty = !deepEqual(get(
|
1168
|
+
if (readFormStateRef.current.dirtyFields && !isCurrentTouched) {
|
1169
|
+
const isPreviousFieldDirty = get(formStateRef.current.dirtyFields, name);
|
1170
|
+
const isCurrentFieldDirty = !deepEqual(get(defaultValuesRef.current, name), inputValue);
|
1060
1171
|
isCurrentFieldDirty
|
1061
|
-
? set(
|
1062
|
-
: unset(
|
1063
|
-
state.dirtyFields =
|
1172
|
+
? set(formStateRef.current.dirtyFields, name, true)
|
1173
|
+
: unset(formStateRef.current.dirtyFields, name);
|
1174
|
+
state.dirtyFields = formStateRef.current.dirtyFields;
|
1064
1175
|
isChanged =
|
1065
|
-
isChanged ||
|
1176
|
+
isChanged ||
|
1177
|
+
isPreviousFieldDirty !== get(formStateRef.current.dirtyFields, name);
|
1066
1178
|
}
|
1067
|
-
const isPreviousFieldTouched = get(
|
1179
|
+
const isPreviousFieldTouched = get(formStateRef.current.touchedFields, name);
|
1068
1180
|
if (isCurrentTouched && !isPreviousFieldTouched) {
|
1069
|
-
set(
|
1070
|
-
state.touchedFields =
|
1181
|
+
set(formStateRef.current.touchedFields, name, isCurrentTouched);
|
1182
|
+
state.touchedFields = formStateRef.current.touchedFields;
|
1071
1183
|
isChanged =
|
1072
1184
|
isChanged ||
|
1073
|
-
(
|
1185
|
+
(readFormStateRef.current.touchedFields &&
|
1074
1186
|
isPreviousFieldTouched !== isCurrentTouched);
|
1075
1187
|
}
|
1076
|
-
isChanged && shouldRender &&
|
1188
|
+
isChanged && shouldRender && subjectsRef.current.state.next(state);
|
1077
1189
|
return isChanged ? state : {};
|
1078
|
-
};
|
1079
|
-
const
|
1080
|
-
|
1081
|
-
? await formOptions.resolver(Object.assign({}, _formValues), formOptions.context, getResolverOptions(name || _names.mount, _fields, formOptions.criteriaMode, formOptions.shouldUseNativeValidation))
|
1082
|
-
: {};
|
1083
|
-
};
|
1084
|
-
const executeBuildinValidation = async (name, skipReRender) => {
|
1085
|
-
const error = (await validateField(get(_fields, name), getValues(name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation))[name];
|
1190
|
+
}, []);
|
1191
|
+
const executeInlineValidation = React.useCallback(async (name, skipReRender) => {
|
1192
|
+
const error = (await validateField(get(fieldsRef.current, name), isValidateAllFieldCriteria, shouldUseNativeValidation))[name];
|
1086
1193
|
await shouldRenderBaseOnError(skipReRender, name, error);
|
1087
1194
|
return isUndefined(error);
|
1088
|
-
};
|
1089
|
-
const executeResolverValidation = async (names) => {
|
1090
|
-
const { errors } = await
|
1195
|
+
}, [isValidateAllFieldCriteria]);
|
1196
|
+
const executeResolverValidation = React.useCallback(async (names) => {
|
1197
|
+
const { errors } = await resolverRef.current(getFieldsValues(fieldsRef), contextRef.current, getResolverOptions(namesRef.current.mount, fieldsRef.current, criteriaMode, shouldUseNativeValidation));
|
1091
1198
|
if (names) {
|
1092
1199
|
for (const name of names) {
|
1093
1200
|
const error = get(errors, name);
|
1094
1201
|
error
|
1095
|
-
? set(
|
1096
|
-
: unset(
|
1202
|
+
? set(formStateRef.current.errors, name, error)
|
1203
|
+
: unset(formStateRef.current.errors, name);
|
1097
1204
|
}
|
1098
1205
|
}
|
1099
1206
|
else {
|
1100
|
-
|
1207
|
+
formStateRef.current.errors = errors;
|
1101
1208
|
}
|
1102
1209
|
return errors;
|
1103
|
-
};
|
1104
|
-
const validateForm = async (
|
1210
|
+
}, [criteriaMode, shouldUseNativeValidation]);
|
1211
|
+
const validateForm = async (fieldsRef, shouldCheckValid, context = {
|
1105
1212
|
valid: true,
|
1106
1213
|
}) => {
|
1107
|
-
for (const name in
|
1108
|
-
const field =
|
1214
|
+
for (const name in fieldsRef) {
|
1215
|
+
const field = fieldsRef[name];
|
1109
1216
|
if (field) {
|
1110
1217
|
const _f = field._f;
|
1111
|
-
const
|
1218
|
+
const current = omit(field, '_f');
|
1112
1219
|
if (_f) {
|
1113
|
-
const fieldError = await validateField(field,
|
1220
|
+
const fieldError = await validateField(field, isValidateAllFieldCriteria, shouldUseNativeValidation);
|
1114
1221
|
if (shouldCheckValid) {
|
1115
1222
|
if (fieldError[_f.name]) {
|
1116
1223
|
context.valid = false;
|
@@ -1119,254 +1226,185 @@ function createFormControl(props = {}) {
|
|
1119
1226
|
}
|
1120
1227
|
else {
|
1121
1228
|
fieldError[_f.name]
|
1122
|
-
? set(
|
1123
|
-
: unset(
|
1229
|
+
? set(formStateRef.current.errors, _f.name, fieldError[_f.name])
|
1230
|
+
: unset(formStateRef.current.errors, _f.name);
|
1124
1231
|
}
|
1125
1232
|
}
|
1126
|
-
|
1233
|
+
current && (await validateForm(current, shouldCheckValid, context));
|
1127
1234
|
}
|
1128
1235
|
}
|
1129
1236
|
return context.valid;
|
1130
1237
|
};
|
1131
|
-
const
|
1132
|
-
|
1238
|
+
const trigger = React.useCallback(async (name, options = {}) => {
|
1239
|
+
const fieldNames = convertToArrayPayload(name);
|
1133
1240
|
let isValid;
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
valError.type && valError.message && (error = valError);
|
1143
|
-
if (valError || get(_formState.errors, parentNodeName)) {
|
1144
|
-
name = parentNodeName;
|
1145
|
-
}
|
1146
|
-
}
|
1147
|
-
isValid = isEmptyObject(errors);
|
1241
|
+
subjectsRef.current.state.next({
|
1242
|
+
isValidating: true,
|
1243
|
+
});
|
1244
|
+
if (resolver) {
|
1245
|
+
const schemaResult = await executeResolverValidation(isUndefined(name) ? name : fieldNames);
|
1246
|
+
isValid = name
|
1247
|
+
? fieldNames.every((name) => !get(schemaResult, name))
|
1248
|
+
: isEmptyObject(schemaResult);
|
1148
1249
|
}
|
1149
1250
|
else {
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
name,
|
1155
|
-
type: target.type,
|
1156
|
-
});
|
1157
|
-
shouldRenderBaseOnError(false, name, error, fieldState, isValid, isWatched);
|
1158
|
-
};
|
1159
|
-
const handleChange = async ({ type, target, target: { value, name, type: inputType }, }) => {
|
1160
|
-
const field = get(_fields, name);
|
1161
|
-
if (field) {
|
1162
|
-
let inputValue = inputType ? getFieldValue(field) : undefined;
|
1163
|
-
inputValue = isUndefined(inputValue) ? value : inputValue;
|
1164
|
-
const isBlurEvent = type === EVENTS.BLUR;
|
1165
|
-
const { isOnBlur: isReValidateOnBlur, isOnChange: isReValidateOnChange } = getValidationModes(formOptions.reValidateMode);
|
1166
|
-
const shouldSkipValidation = (!hasValidation(field._f, field._f.mount) &&
|
1167
|
-
!formOptions.resolver &&
|
1168
|
-
!get(_formState.errors, name)) ||
|
1169
|
-
skipValidation(Object.assign({ isBlurEvent, isTouched: !!get(_formState.touchedFields, name), isSubmitted: _formState.isSubmitted, isReValidateOnBlur,
|
1170
|
-
isReValidateOnChange }, validationMode));
|
1171
|
-
const isWatched = !isBlurEvent && isFieldWatched(name);
|
1172
|
-
if (!isUndefined(inputValue)) {
|
1173
|
-
set(_formValues, name, inputValue);
|
1174
|
-
}
|
1175
|
-
const fieldState = updateTouchAndDirtyState(name, inputValue, isBlurEvent, false);
|
1176
|
-
const shouldRender = !isEmptyObject(fieldState) || isWatched;
|
1177
|
-
if (shouldSkipValidation) {
|
1178
|
-
!isBlurEvent &&
|
1179
|
-
_subjects.watch.next({
|
1180
|
-
name,
|
1181
|
-
type,
|
1182
|
-
});
|
1183
|
-
return (shouldRender &&
|
1184
|
-
_subjects.state.next(isWatched ? { name } : Object.assign(Object.assign({}, fieldState), { name })));
|
1185
|
-
}
|
1186
|
-
_subjects.state.next({
|
1187
|
-
isValidating: true,
|
1188
|
-
});
|
1189
|
-
if (get(_formState.errors, name) || !formOptions.delayError) {
|
1190
|
-
handleValidate(target, fieldState, isWatched, isBlurEvent);
|
1251
|
+
if (name) {
|
1252
|
+
isValid = (await Promise.all(fieldNames
|
1253
|
+
.filter((fieldName) => get(fieldsRef.current, fieldName, {})._f)
|
1254
|
+
.map(async (fieldName) => await executeInlineValidation(fieldName, true)))).every(Boolean);
|
1191
1255
|
}
|
1192
1256
|
else {
|
1193
|
-
|
1194
|
-
|
1195
|
-
_delayCallback(target, fieldState, isWatched, isBlurEvent);
|
1196
|
-
isWatched && _subjects.state.next({ name });
|
1257
|
+
await validateForm(fieldsRef.current);
|
1258
|
+
isValid = isEmptyObject(formStateRef.current.errors);
|
1197
1259
|
}
|
1198
1260
|
}
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1261
|
+
subjectsRef.current.state.next(Object.assign(Object.assign({}, (isString(name) ? { name } : {})), { errors: formStateRef.current.errors, isValidating: false }));
|
1262
|
+
if (options.shouldFocus && !isValid) {
|
1263
|
+
focusFieldBy(fieldsRef.current, (key) => get(formStateRef.current.errors, key), name ? fieldNames : namesRef.current.mount);
|
1264
|
+
}
|
1265
|
+
readFormStateRef.current.isValid && updateIsValid();
|
1266
|
+
return isValid;
|
1267
|
+
}, [executeResolverValidation, executeInlineValidation]);
|
1268
|
+
const updateIsValidAndInputValue = (name, ref, shouldSkipValueAs) => {
|
1269
|
+
const field = get(fieldsRef.current, name);
|
1202
1270
|
if (field) {
|
1203
|
-
const
|
1204
|
-
const isValueUndefined = isUndefined(fieldValue);
|
1271
|
+
const isValueUndefined = isUndefined(field._f.value);
|
1205
1272
|
const defaultValue = isValueUndefined
|
1206
|
-
? get(
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1273
|
+
? isUndefined(get(fieldArrayDefaultValuesRef.current, name))
|
1274
|
+
? get(defaultValuesRef.current, name)
|
1275
|
+
: get(fieldArrayDefaultValuesRef.current, name)
|
1276
|
+
: field._f.value;
|
1277
|
+
if (!isUndefined(defaultValue)) {
|
1278
|
+
if (ref && ref.defaultChecked) {
|
1279
|
+
field._f.value = getFieldValue(field);
|
1280
|
+
}
|
1281
|
+
else if (shouldSkipValueAs) {
|
1282
|
+
field._f.value = defaultValue;
|
1283
|
+
}
|
1284
|
+
else {
|
1285
|
+
setFieldValue(name, defaultValue);
|
1286
|
+
}
|
1211
1287
|
}
|
1212
|
-
else {
|
1213
|
-
|
1288
|
+
else if (isValueUndefined) {
|
1289
|
+
field._f.value = getFieldValue(field);
|
1214
1290
|
}
|
1215
1291
|
}
|
1216
|
-
|
1217
|
-
};
|
1218
|
-
const _getIsDirty = (name, data) => {
|
1219
|
-
name && data && set(_formValues, name, data);
|
1220
|
-
return !deepEqual(Object.assign({}, getValues()), _defaultValues);
|
1292
|
+
isMountedRef.current && readFormStateRef.current.isValid && updateIsValid();
|
1221
1293
|
};
|
1222
|
-
const
|
1223
|
-
const isValid =
|
1224
|
-
? isEmptyObject((await
|
1225
|
-
: await validateForm(
|
1226
|
-
if (isValid !==
|
1227
|
-
|
1228
|
-
|
1294
|
+
const updateIsValid = React.useCallback(async (values = {}) => {
|
1295
|
+
const isValid = resolver
|
1296
|
+
? isEmptyObject((await resolverRef.current(Object.assign(Object.assign({}, getFieldsValues(fieldsRef)), values), contextRef.current, getResolverOptions(namesRef.current.mount, fieldsRef.current, criteriaMode, shouldUseNativeValidation))).errors)
|
1297
|
+
: await validateForm(fieldsRef.current, true);
|
1298
|
+
if (isValid !== formStateRef.current.isValid) {
|
1299
|
+
formStateRef.current.isValid = isValid;
|
1300
|
+
subjectsRef.current.state.next({
|
1229
1301
|
isValid,
|
1230
1302
|
});
|
1231
1303
|
}
|
1232
|
-
};
|
1233
|
-
const
|
1304
|
+
}, [criteriaMode, shouldUseNativeValidation]);
|
1305
|
+
const setValues = React.useCallback((name, value, options) => Object.entries(value).forEach(([fieldKey, fieldValue]) => {
|
1234
1306
|
const fieldName = `${name}.${fieldKey}`;
|
1235
|
-
const field = get(
|
1236
|
-
const isFieldArray =
|
1307
|
+
const field = get(fieldsRef.current, fieldName);
|
1308
|
+
const isFieldArray = namesRef.current.array.has(name);
|
1237
1309
|
(isFieldArray || !isPrimitive(fieldValue) || (field && !field._f)) &&
|
1238
1310
|
!isDateObject(fieldValue)
|
1239
|
-
?
|
1311
|
+
? setValues(fieldName, fieldValue, options)
|
1240
1312
|
: setFieldValue(fieldName, fieldValue, options, true, !field);
|
1241
|
-
});
|
1242
|
-
const _getWatch = (fieldNames, defaultValue, isGlobal) => {
|
1243
|
-
const fieldValues = Object.assign({}, (_isMounted
|
1244
|
-
? Object.assign({}, Object.assign(Object.assign({}, _defaultValues), _formValues)) : isUndefined(defaultValue)
|
1245
|
-
? _defaultValues
|
1246
|
-
: defaultValue));
|
1247
|
-
if (!fieldNames) {
|
1248
|
-
isGlobal && (_names.watchAll = true);
|
1249
|
-
return fieldValues;
|
1250
|
-
}
|
1251
|
-
const result = [];
|
1252
|
-
for (const fieldName of convertToArrayPayload(fieldNames)) {
|
1253
|
-
isGlobal && _names.watch.add(fieldName);
|
1254
|
-
result.push(get(fieldValues, fieldName));
|
1255
|
-
}
|
1256
|
-
return Array.isArray(fieldNames)
|
1257
|
-
? result
|
1258
|
-
: isObject(result[0])
|
1259
|
-
? Object.assign({}, result[0]) : Array.isArray(result[0])
|
1260
|
-
? [...result[0]]
|
1261
|
-
: result[0];
|
1262
|
-
};
|
1263
|
-
const _updateFormValues = (defaultValues, name = '') => {
|
1264
|
-
for (const key in defaultValues) {
|
1265
|
-
const value = defaultValues[key];
|
1266
|
-
const fieldName = name + (name ? '.' : '') + key;
|
1267
|
-
const field = get(_fields, fieldName);
|
1268
|
-
if (!field || !field._f) {
|
1269
|
-
if (isObject(value) || Array.isArray(value)) {
|
1270
|
-
_updateFormValues(value, fieldName);
|
1271
|
-
}
|
1272
|
-
else if (!field) {
|
1273
|
-
set(_formValues, fieldName, value);
|
1274
|
-
}
|
1275
|
-
}
|
1276
|
-
}
|
1277
|
-
};
|
1278
|
-
const _bathFieldArrayUpdate = (keyName, name, method, args, updatedFieldArrayValues = [], shouldSet = true) => {
|
1279
|
-
_isInAction = true;
|
1280
|
-
if (get(_fields, name)) {
|
1281
|
-
const output = method(get(_fields, name), args.argA, args.argB);
|
1282
|
-
shouldSet && set(_fields, name, output);
|
1283
|
-
}
|
1284
|
-
set(_formValues, name, updatedFieldArrayValues);
|
1285
|
-
if (Array.isArray(get(_formState.errors, name))) {
|
1286
|
-
const output = method(get(_formState.errors, name), args.argA, args.argB);
|
1287
|
-
shouldSet && set(_formState.errors, name, output);
|
1288
|
-
unsetEmptyArray(_formState.errors, name);
|
1289
|
-
}
|
1290
|
-
if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
|
1291
|
-
const output = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
1292
|
-
shouldSet && set(_formState.touchedFields, name, output);
|
1293
|
-
unsetEmptyArray(_formState.touchedFields, name);
|
1294
|
-
}
|
1295
|
-
if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
|
1296
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1297
|
-
updatedFieldArrayValues &&
|
1298
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1299
|
-
unsetEmptyArray(_formState.dirtyFields, name);
|
1300
|
-
}
|
1301
|
-
_subjects.state.next({
|
1302
|
-
isDirty: _getIsDirty(name, omitKey(updatedFieldArrayValues, keyName)),
|
1303
|
-
dirtyFields: _formState.dirtyFields,
|
1304
|
-
errors: _formState.errors,
|
1305
|
-
isValid: _formState.isValid,
|
1306
|
-
});
|
1307
|
-
};
|
1308
|
-
const _getFieldArrayValue = (name) => get(_isMounted ? _formValues : _defaultValues, name, []);
|
1313
|
+
}), [trigger]);
|
1309
1314
|
const setValue = (name, value, options = {}) => {
|
1310
|
-
const field = get(
|
1311
|
-
const isFieldArray =
|
1315
|
+
const field = get(fieldsRef.current, name);
|
1316
|
+
const isFieldArray = namesRef.current.array.has(name);
|
1312
1317
|
if (isFieldArray) {
|
1313
|
-
|
1318
|
+
subjectsRef.current.array.next({
|
1314
1319
|
values: value,
|
1315
1320
|
name,
|
1316
1321
|
isReset: true,
|
1317
1322
|
});
|
1318
|
-
if ((
|
1323
|
+
if ((readFormStateRef.current.isDirty ||
|
1324
|
+
readFormStateRef.current.dirtyFields) &&
|
1319
1325
|
options.shouldDirty) {
|
1320
|
-
set(
|
1321
|
-
|
1326
|
+
set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(value, get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
|
1327
|
+
subjectsRef.current.state.next({
|
1322
1328
|
name,
|
1323
|
-
dirtyFields:
|
1324
|
-
isDirty:
|
1329
|
+
dirtyFields: formStateRef.current.dirtyFields,
|
1330
|
+
isDirty: getIsDirty(name, value),
|
1325
1331
|
});
|
1326
1332
|
}
|
1327
|
-
!value.length &&
|
1333
|
+
!value.length &&
|
1334
|
+
set(fieldsRef.current, name, []) &&
|
1335
|
+
set(fieldArrayDefaultValuesRef.current, name, []);
|
1328
1336
|
}
|
1329
|
-
set(_formValues, name, value);
|
1330
1337
|
((field && !field._f) || isFieldArray) && !isNullOrUndefined(value)
|
1331
|
-
?
|
1338
|
+
? setValues(name, value, isFieldArray ? {} : options)
|
1332
1339
|
: setFieldValue(name, value, options, true, !field);
|
1333
|
-
isFieldWatched(name) &&
|
1334
|
-
|
1335
|
-
name,
|
1336
|
-
});
|
1340
|
+
isFieldWatched(name) && subjectsRef.current.state.next({});
|
1341
|
+
subjectsRef.current.watch.next({ name, values: getValues() });
|
1337
1342
|
};
|
1338
|
-
const
|
1339
|
-
|
1343
|
+
const handleValidate = async (target, fieldState, isWatched, isBlurEvent) => {
|
1344
|
+
let error;
|
1340
1345
|
let isValid;
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1346
|
+
let name = target.name;
|
1347
|
+
const field = get(fieldsRef.current, name);
|
1348
|
+
if (resolver) {
|
1349
|
+
const { errors } = await resolverRef.current(getFieldsValues(fieldsRef), contextRef.current, getResolverOptions([name], fieldsRef.current, criteriaMode, shouldUseNativeValidation));
|
1350
|
+
error = get(errors, name);
|
1351
|
+
if (isCheckBoxInput(target) && !error) {
|
1352
|
+
const parentNodeName = getNodeParentName(name);
|
1353
|
+
const currentError = get(errors, parentNodeName, {});
|
1354
|
+
currentError.type && currentError.message && (error = currentError);
|
1355
|
+
if (currentError || get(formStateRef.current.errors, parentNodeName)) {
|
1356
|
+
name = parentNodeName;
|
1357
|
+
}
|
1358
|
+
}
|
1359
|
+
isValid = isEmptyObject(errors);
|
1349
1360
|
}
|
1350
1361
|
else {
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1362
|
+
error = (await validateField(field, isValidateAllFieldCriteria, shouldUseNativeValidation))[name];
|
1363
|
+
}
|
1364
|
+
!isBlurEvent &&
|
1365
|
+
subjectsRef.current.watch.next({
|
1366
|
+
name,
|
1367
|
+
type: target.type,
|
1368
|
+
values: getValues(),
|
1369
|
+
});
|
1370
|
+
shouldRenderBaseOnError(false, name, error, fieldState, isValid, isWatched);
|
1371
|
+
};
|
1372
|
+
const handleChange = React.useCallback(async ({ type, target, target: { value, name, type: inputType } }) => {
|
1373
|
+
const field = get(fieldsRef.current, name);
|
1374
|
+
if (field) {
|
1375
|
+
let inputValue = inputType ? getFieldValue(field) : undefined;
|
1376
|
+
inputValue = isUndefined(inputValue) ? value : inputValue;
|
1377
|
+
const isBlurEvent = type === EVENTS.BLUR;
|
1378
|
+
const { isOnBlur: isReValidateOnBlur, isOnChange: isReValidateOnChange, } = getValidationModes(reValidateMode);
|
1379
|
+
const shouldSkipValidation = (!hasValidation(field._f, field._f.mount) &&
|
1380
|
+
!resolver &&
|
1381
|
+
!get(formStateRef.current.errors, name)) ||
|
1382
|
+
skipValidation(Object.assign({ isBlurEvent, isTouched: !!get(formStateRef.current.touchedFields, name), isSubmitted: formStateRef.current.isSubmitted, isReValidateOnBlur,
|
1383
|
+
isReValidateOnChange }, validationMode));
|
1384
|
+
const isWatched = !isBlurEvent && isFieldWatched(name);
|
1385
|
+
if (!isUndefined(inputValue)) {
|
1386
|
+
field._f.value = inputValue;
|
1355
1387
|
}
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1388
|
+
const fieldState = updateTouchAndDirtyState(name, field._f.value, isBlurEvent, false);
|
1389
|
+
const shouldRender = !isEmptyObject(fieldState) || isWatched;
|
1390
|
+
if (shouldSkipValidation) {
|
1391
|
+
!isBlurEvent &&
|
1392
|
+
subjectsRef.current.watch.next({
|
1393
|
+
name,
|
1394
|
+
type,
|
1395
|
+
values: getValues(),
|
1396
|
+
});
|
1397
|
+
return (shouldRender &&
|
1398
|
+
subjectsRef.current.state.next(isWatched ? { name } : Object.assign(Object.assign({}, fieldState), { name })));
|
1359
1399
|
}
|
1400
|
+
subjectsRef.current.state.next({
|
1401
|
+
isValidating: true,
|
1402
|
+
});
|
1403
|
+
handleValidate(target, fieldState, isWatched, isBlurEvent);
|
1360
1404
|
}
|
1361
|
-
|
1362
|
-
if (options.shouldFocus && !isValid) {
|
1363
|
-
focusFieldBy(_fields, (key) => get(_formState.errors, key), name ? fieldNames : _names.mount);
|
1364
|
-
}
|
1365
|
-
_proxyFormState.isValid && _updateValid();
|
1366
|
-
return isValid;
|
1367
|
-
};
|
1405
|
+
}, []);
|
1368
1406
|
const getValues = (fieldNames) => {
|
1369
|
-
const values = Object.assign(Object.assign({},
|
1407
|
+
const values = Object.assign(Object.assign({}, defaultValuesRef.current), getFieldsValues(fieldsRef));
|
1370
1408
|
return isUndefined(fieldNames)
|
1371
1409
|
? values
|
1372
1410
|
: isString(fieldNames)
|
@@ -1375,51 +1413,73 @@ function createFormControl(props = {}) {
|
|
1375
1413
|
};
|
1376
1414
|
const clearErrors = (name) => {
|
1377
1415
|
name
|
1378
|
-
? convertToArrayPayload(name).forEach((inputName) => unset(
|
1379
|
-
: (
|
1380
|
-
|
1381
|
-
errors:
|
1416
|
+
? convertToArrayPayload(name).forEach((inputName) => unset(formStateRef.current.errors, inputName))
|
1417
|
+
: (formStateRef.current.errors = {});
|
1418
|
+
subjectsRef.current.state.next({
|
1419
|
+
errors: formStateRef.current.errors,
|
1382
1420
|
});
|
1383
1421
|
};
|
1384
1422
|
const setError = (name, error, options) => {
|
1385
|
-
const ref = ((get(
|
1386
|
-
set(
|
1387
|
-
|
1423
|
+
const ref = ((get(fieldsRef.current, name) || { _f: {} })._f || {}).ref;
|
1424
|
+
set(formStateRef.current.errors, name, Object.assign(Object.assign({}, error), { ref }));
|
1425
|
+
subjectsRef.current.state.next({
|
1388
1426
|
name,
|
1389
|
-
errors:
|
1427
|
+
errors: formStateRef.current.errors,
|
1390
1428
|
isValid: false,
|
1391
1429
|
});
|
1392
1430
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
1393
1431
|
};
|
1432
|
+
const watchInternal = React.useCallback((fieldNames, defaultValue, isGlobal, formValues) => {
|
1433
|
+
const isArrayNames = Array.isArray(fieldNames);
|
1434
|
+
const fieldValues = formValues || isMountedRef.current
|
1435
|
+
? Object.assign(Object.assign({}, defaultValuesRef.current), (formValues || getFieldsValues(fieldsRef))) : isUndefined(defaultValue)
|
1436
|
+
? defaultValuesRef.current
|
1437
|
+
: isArrayNames
|
1438
|
+
? defaultValue
|
1439
|
+
: { [fieldNames]: defaultValue };
|
1440
|
+
if (isUndefined(fieldNames)) {
|
1441
|
+
isGlobal && (namesRef.current.watchAll = true);
|
1442
|
+
return fieldValues;
|
1443
|
+
}
|
1444
|
+
const result = [];
|
1445
|
+
for (const fieldName of convertToArrayPayload(fieldNames)) {
|
1446
|
+
isGlobal && namesRef.current.watch.add(fieldName);
|
1447
|
+
result.push(get(fieldValues, fieldName));
|
1448
|
+
}
|
1449
|
+
return isArrayNames ? result : result[0];
|
1450
|
+
}, []);
|
1394
1451
|
const watch = (fieldName, defaultValue) => isFunction(fieldName)
|
1395
|
-
?
|
1396
|
-
next: (info) => fieldName(
|
1452
|
+
? subjectsRef.current.watch.subscribe({
|
1453
|
+
next: (info) => fieldName(watchInternal(undefined, defaultValue), info),
|
1397
1454
|
})
|
1398
|
-
:
|
1455
|
+
: watchInternal(fieldName, defaultValue, true);
|
1399
1456
|
const unregister = (name, options = {}) => {
|
1400
|
-
for (const inputName of name
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
!options.
|
1409
|
-
|
1410
|
-
!options.keepTouched &&
|
1411
|
-
|
1457
|
+
for (const inputName of name
|
1458
|
+
? convertToArrayPayload(name)
|
1459
|
+
: namesRef.current.mount) {
|
1460
|
+
namesRef.current.mount.delete(inputName);
|
1461
|
+
namesRef.current.array.delete(inputName);
|
1462
|
+
if (get(fieldsRef.current, inputName)) {
|
1463
|
+
!options.keepError && unset(formStateRef.current.errors, inputName);
|
1464
|
+
!options.keepValue && unset(fieldsRef.current, inputName);
|
1465
|
+
!options.keepDirty &&
|
1466
|
+
unset(formStateRef.current.dirtyFields, inputName);
|
1467
|
+
!options.keepTouched &&
|
1468
|
+
unset(formStateRef.current.touchedFields, inputName);
|
1469
|
+
!shouldUnregister &&
|
1412
1470
|
!options.keepDefaultValue &&
|
1413
|
-
unset(
|
1471
|
+
unset(defaultValuesRef.current, inputName);
|
1414
1472
|
}
|
1415
1473
|
}
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1474
|
+
subjectsRef.current.watch.next({
|
1475
|
+
values: getValues(),
|
1476
|
+
});
|
1477
|
+
subjectsRef.current.state.next(Object.assign(Object.assign({}, formStateRef.current), (!options.keepDirty ? {} : { isDirty: getIsDirty() })));
|
1478
|
+
!options.keepIsValid && updateIsValid();
|
1419
1479
|
};
|
1420
1480
|
const registerFieldRef = (name, ref, options) => {
|
1421
1481
|
register(name, options);
|
1422
|
-
let field = get(
|
1482
|
+
let field = get(fieldsRef.current, name);
|
1423
1483
|
const isRadioOrCheckbox = isRadioOrCheckboxFunction(ref);
|
1424
1484
|
if (ref === field._f.ref ||
|
1425
1485
|
(isRadioOrCheckbox &&
|
@@ -1433,76 +1493,77 @@ function createFormControl(props = {}) {
|
|
1433
1493
|
ref,
|
1434
1494
|
], ref: { type: ref.type, name } }) : Object.assign(Object.assign({}, field._f), { ref }),
|
1435
1495
|
};
|
1436
|
-
set(
|
1437
|
-
|
1496
|
+
set(fieldsRef.current, name, field);
|
1497
|
+
updateIsValidAndInputValue(name, ref);
|
1438
1498
|
};
|
1439
|
-
const register = (name, options = {}) => {
|
1440
|
-
const field = get(
|
1441
|
-
set(
|
1499
|
+
const register = React.useCallback((name, options = {}) => {
|
1500
|
+
const field = get(fieldsRef.current, name);
|
1501
|
+
set(fieldsRef.current, name, {
|
1442
1502
|
_f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
|
1443
1503
|
});
|
1444
|
-
|
1445
|
-
|
1446
|
-
}
|
1447
|
-
if (!isUndefined(options.disabled) &&
|
1448
|
-
field &&
|
1449
|
-
field._f &&
|
1450
|
-
field._f.ref.disabled !== options.disabled) {
|
1451
|
-
set(_formValues, name, options.disabled ? undefined : field._f.ref.value);
|
1452
|
-
}
|
1453
|
-
_names.mount.add(name);
|
1454
|
-
!field && _updateValidAndInputValue(name);
|
1504
|
+
namesRef.current.mount.add(name);
|
1505
|
+
!field && updateIsValidAndInputValue(name, undefined, true);
|
1455
1506
|
return isWindowUndefined
|
1456
1507
|
? { name: name }
|
1457
|
-
:
|
1458
|
-
|
1459
|
-
|
1508
|
+
: {
|
1509
|
+
name,
|
1510
|
+
onChange: handleChange,
|
1511
|
+
onBlur: handleChange,
|
1512
|
+
ref: (ref) => {
|
1460
1513
|
if (ref) {
|
1461
1514
|
registerFieldRef(name, ref, options);
|
1462
1515
|
}
|
1463
1516
|
else {
|
1464
|
-
const field = get(
|
1465
|
-
const
|
1517
|
+
const field = get(fieldsRef.current, name, {});
|
1518
|
+
const shouldUnmount = shouldUnregister || options.shouldUnregister;
|
1466
1519
|
if (field._f) {
|
1467
1520
|
field._f.mount = false;
|
1521
|
+
// If initial state of field element is disabled,
|
1522
|
+
// value is not set on first "register"
|
1523
|
+
// re-sync the value in when it switched to enabled
|
1524
|
+
if (isUndefined(field._f.value)) {
|
1525
|
+
field._f.value = field._f.ref.value;
|
1526
|
+
}
|
1468
1527
|
}
|
1469
|
-
|
1470
|
-
!(isNameInFieldArray(
|
1471
|
-
|
1528
|
+
shouldUnmount &&
|
1529
|
+
!(isNameInFieldArray(namesRef.current.array, name) &&
|
1530
|
+
inFieldArrayActionRef.current) &&
|
1531
|
+
namesRef.current.unMount.add(name);
|
1472
1532
|
}
|
1473
|
-
}
|
1474
|
-
|
1475
|
-
|
1533
|
+
},
|
1534
|
+
};
|
1535
|
+
}, []);
|
1536
|
+
const handleSubmit = React.useCallback((onValid, onInvalid) => async (e) => {
|
1476
1537
|
if (e) {
|
1477
1538
|
e.preventDefault && e.preventDefault();
|
1478
1539
|
e.persist && e.persist();
|
1479
1540
|
}
|
1480
1541
|
let hasNoPromiseError = true;
|
1481
|
-
let fieldValues =
|
1482
|
-
|
1542
|
+
let fieldValues = getFieldsValues(fieldsRef);
|
1543
|
+
subjectsRef.current.state.next({
|
1483
1544
|
isSubmitting: true,
|
1484
1545
|
});
|
1485
1546
|
try {
|
1486
|
-
if (
|
1487
|
-
const { errors, values } = await
|
1488
|
-
|
1547
|
+
if (resolver) {
|
1548
|
+
const { errors, values } = await resolverRef.current(fieldValues, contextRef.current, getResolverOptions(namesRef.current.mount, fieldsRef.current, criteriaMode, shouldUseNativeValidation));
|
1549
|
+
formStateRef.current.errors = errors;
|
1489
1550
|
fieldValues = values;
|
1490
1551
|
}
|
1491
1552
|
else {
|
1492
|
-
await validateForm(
|
1553
|
+
await validateForm(fieldsRef.current);
|
1493
1554
|
}
|
1494
|
-
if (isEmptyObject(
|
1495
|
-
Object.keys(
|
1496
|
-
|
1555
|
+
if (isEmptyObject(formStateRef.current.errors) &&
|
1556
|
+
Object.keys(formStateRef.current.errors).every((name) => get(fieldValues, name))) {
|
1557
|
+
subjectsRef.current.state.next({
|
1497
1558
|
errors: {},
|
1498
1559
|
isSubmitting: true,
|
1499
1560
|
});
|
1500
1561
|
await onValid(fieldValues, e);
|
1501
1562
|
}
|
1502
1563
|
else {
|
1503
|
-
onInvalid && (await onInvalid(
|
1504
|
-
|
1505
|
-
focusFieldBy(
|
1564
|
+
onInvalid && (await onInvalid(formStateRef.current.errors, e));
|
1565
|
+
shouldFocusError &&
|
1566
|
+
focusFieldBy(fieldsRef.current, (key) => get(formStateRef.current.errors, key), namesRef.current.mount);
|
1506
1567
|
}
|
1507
1568
|
}
|
1508
1569
|
catch (err) {
|
@@ -1510,21 +1571,41 @@ function createFormControl(props = {}) {
|
|
1510
1571
|
throw err;
|
1511
1572
|
}
|
1512
1573
|
finally {
|
1513
|
-
|
1514
|
-
|
1574
|
+
formStateRef.current.isSubmitted = true;
|
1575
|
+
subjectsRef.current.state.next({
|
1515
1576
|
isSubmitted: true,
|
1516
1577
|
isSubmitting: false,
|
1517
|
-
isSubmitSuccessful: isEmptyObject(
|
1518
|
-
submitCount:
|
1519
|
-
errors:
|
1578
|
+
isSubmitSuccessful: isEmptyObject(formStateRef.current.errors) && hasNoPromiseError,
|
1579
|
+
submitCount: formStateRef.current.submitCount + 1,
|
1580
|
+
errors: formStateRef.current.errors,
|
1520
1581
|
});
|
1521
1582
|
}
|
1583
|
+
}, [
|
1584
|
+
shouldFocusError,
|
1585
|
+
isValidateAllFieldCriteria,
|
1586
|
+
criteriaMode,
|
1587
|
+
shouldUseNativeValidation,
|
1588
|
+
]);
|
1589
|
+
const registerAbsentFields = (defaultValues, name = '') => {
|
1590
|
+
for (const key in defaultValues) {
|
1591
|
+
const value = defaultValues[key];
|
1592
|
+
const fieldName = name + (name ? '.' : '') + key;
|
1593
|
+
const field = get(fieldsRef.current, fieldName);
|
1594
|
+
if (!field || !field._f) {
|
1595
|
+
if (isObject(value) || Array.isArray(value)) {
|
1596
|
+
registerAbsentFields(value, fieldName);
|
1597
|
+
}
|
1598
|
+
else if (!field) {
|
1599
|
+
register(fieldName, { value });
|
1600
|
+
}
|
1601
|
+
}
|
1602
|
+
}
|
1522
1603
|
};
|
1523
1604
|
const reset = (values, keepStateOptions = {}) => {
|
1524
|
-
const updatedValues = values ||
|
1605
|
+
const updatedValues = values || defaultValuesRef.current;
|
1525
1606
|
if (isWeb && !keepStateOptions.keepValues) {
|
1526
|
-
for (const name of
|
1527
|
-
const field = get(
|
1607
|
+
for (const name of namesRef.current.mount) {
|
1608
|
+
const field = get(fieldsRef.current, name);
|
1528
1609
|
if (field && field._f) {
|
1529
1610
|
const inputRef = Array.isArray(field._f.refs)
|
1530
1611
|
? field._f.refs[0]
|
@@ -1538,160 +1619,71 @@ function createFormControl(props = {}) {
|
|
1538
1619
|
}
|
1539
1620
|
}
|
1540
1621
|
if (!keepStateOptions.keepDefaultValues) {
|
1541
|
-
|
1542
|
-
|
1622
|
+
defaultValuesRef.current = Object.assign({}, updatedValues);
|
1623
|
+
fieldArrayDefaultValuesRef.current = Object.assign({}, updatedValues);
|
1543
1624
|
}
|
1544
1625
|
if (!keepStateOptions.keepValues) {
|
1545
|
-
|
1546
|
-
|
1547
|
-
_subjects.control.next({
|
1626
|
+
fieldsRef.current = {};
|
1627
|
+
subjectsRef.current.control.next({
|
1548
1628
|
values: keepStateOptions.keepDefaultValues
|
1549
|
-
?
|
1629
|
+
? defaultValuesRef.current
|
1550
1630
|
: Object.assign({}, updatedValues),
|
1551
1631
|
});
|
1552
|
-
|
1553
|
-
|
1632
|
+
subjectsRef.current.watch.next({
|
1633
|
+
values: Object.assign({}, updatedValues),
|
1634
|
+
});
|
1635
|
+
subjectsRef.current.array.next({
|
1554
1636
|
values: Object.assign({}, updatedValues),
|
1555
1637
|
isReset: true,
|
1556
1638
|
});
|
1557
1639
|
}
|
1558
|
-
|
1640
|
+
namesRef.current = {
|
1559
1641
|
mount: new Set(),
|
1560
1642
|
unMount: new Set(),
|
1561
1643
|
array: new Set(),
|
1562
1644
|
watch: new Set(),
|
1563
1645
|
watchAll: false,
|
1564
1646
|
};
|
1565
|
-
|
1647
|
+
subjectsRef.current.state.next({
|
1566
1648
|
submitCount: keepStateOptions.keepSubmitCount
|
1567
|
-
?
|
1649
|
+
? formStateRef.current.submitCount
|
1568
1650
|
: 0,
|
1569
1651
|
isDirty: keepStateOptions.keepDirty
|
1570
|
-
?
|
1652
|
+
? formStateRef.current.isDirty
|
1571
1653
|
: keepStateOptions.keepDefaultValues
|
1572
|
-
? deepEqual(values,
|
1654
|
+
? deepEqual(values, defaultValuesRef.current)
|
1573
1655
|
: false,
|
1574
1656
|
isSubmitted: keepStateOptions.keepIsSubmitted
|
1575
|
-
?
|
1657
|
+
? formStateRef.current.isSubmitted
|
1576
1658
|
: false,
|
1577
|
-
dirtyFields: keepStateOptions.keepDirty
|
1659
|
+
dirtyFields: keepStateOptions.keepDirty
|
1660
|
+
? formStateRef.current.dirtyFields
|
1661
|
+
: {},
|
1578
1662
|
touchedFields: keepStateOptions.keepTouched
|
1579
|
-
?
|
1663
|
+
? formStateRef.current.touchedFields
|
1580
1664
|
: {},
|
1581
|
-
errors: keepStateOptions.keepErrors ?
|
1665
|
+
errors: keepStateOptions.keepErrors ? formStateRef.current.errors : {},
|
1582
1666
|
isSubmitting: false,
|
1583
1667
|
isSubmitSuccessful: false,
|
1584
1668
|
});
|
1585
|
-
|
1669
|
+
isMountedRef.current = !!keepStateOptions.keepIsValid;
|
1586
1670
|
};
|
1587
|
-
const setFocus = (name) => get(
|
1588
|
-
return {
|
1589
|
-
control: {
|
1590
|
-
register,
|
1591
|
-
unregister,
|
1592
|
-
_setValues,
|
1593
|
-
_getIsDirty,
|
1594
|
-
_getWatch,
|
1595
|
-
_updateValid,
|
1596
|
-
_updateFormValues,
|
1597
|
-
_bathFieldArrayUpdate,
|
1598
|
-
_getFieldArrayValue,
|
1599
|
-
_subjects,
|
1600
|
-
_shouldUnregister: formOptions.shouldUnregister,
|
1601
|
-
_fields,
|
1602
|
-
_proxyFormState,
|
1603
|
-
get _formValues() {
|
1604
|
-
return _formValues;
|
1605
|
-
},
|
1606
|
-
set _formValues(value) {
|
1607
|
-
_formValues = value;
|
1608
|
-
},
|
1609
|
-
get _isMounted() {
|
1610
|
-
return _isMounted;
|
1611
|
-
},
|
1612
|
-
set _isMounted(value) {
|
1613
|
-
_isMounted = value;
|
1614
|
-
},
|
1615
|
-
get _defaultValues() {
|
1616
|
-
return _defaultValues;
|
1617
|
-
},
|
1618
|
-
set _defaultValues(value) {
|
1619
|
-
_defaultValues = value;
|
1620
|
-
},
|
1621
|
-
get _names() {
|
1622
|
-
return _names;
|
1623
|
-
},
|
1624
|
-
set _names(value) {
|
1625
|
-
_names = value;
|
1626
|
-
},
|
1627
|
-
_isInAction: {
|
1628
|
-
get val() {
|
1629
|
-
return _isInAction;
|
1630
|
-
},
|
1631
|
-
set val(value) {
|
1632
|
-
_isInAction = value;
|
1633
|
-
},
|
1634
|
-
},
|
1635
|
-
_formState: {
|
1636
|
-
get val() {
|
1637
|
-
return _formState;
|
1638
|
-
},
|
1639
|
-
set val(value) {
|
1640
|
-
_formState = value;
|
1641
|
-
},
|
1642
|
-
},
|
1643
|
-
_updateProps: (options) => {
|
1644
|
-
formOptions = Object.assign(Object.assign({}, defaultOptions), options);
|
1645
|
-
},
|
1646
|
-
},
|
1647
|
-
trigger,
|
1648
|
-
register,
|
1649
|
-
handleSubmit,
|
1650
|
-
watch,
|
1651
|
-
setValue,
|
1652
|
-
getValues,
|
1653
|
-
reset,
|
1654
|
-
clearErrors,
|
1655
|
-
unregister,
|
1656
|
-
setError,
|
1657
|
-
setFocus,
|
1658
|
-
};
|
1659
|
-
}
|
1660
|
-
|
1661
|
-
var live = (ref) => !isHTMLElement(ref) || !document.contains(ref);
|
1662
|
-
|
1663
|
-
function useForm(props = {}) {
|
1664
|
-
const _formControl = React.useRef();
|
1665
|
-
const [formState, updateFormState] = React.useState({
|
1666
|
-
isDirty: false,
|
1667
|
-
isValidating: false,
|
1668
|
-
dirtyFields: {},
|
1669
|
-
isSubmitted: false,
|
1670
|
-
submitCount: 0,
|
1671
|
-
touchedFields: {},
|
1672
|
-
isSubmitting: false,
|
1673
|
-
isSubmitSuccessful: false,
|
1674
|
-
isValid: false,
|
1675
|
-
errors: {},
|
1676
|
-
});
|
1677
|
-
_formControl.current
|
1678
|
-
? _formControl.current.control._updateProps(props)
|
1679
|
-
: (_formControl.current = createFormControl(props));
|
1680
|
-
const control = _formControl.current.control;
|
1671
|
+
const setFocus = (name) => get(fieldsRef.current, name)._f.ref.focus();
|
1681
1672
|
React.useEffect(() => {
|
1682
|
-
const formStateSubscription =
|
1673
|
+
const formStateSubscription = subjectsRef.current.state.subscribe({
|
1683
1674
|
next(formState) {
|
1684
|
-
if (shouldRenderFormState(formState,
|
1685
|
-
|
1686
|
-
updateFormState(
|
1675
|
+
if (shouldRenderFormState(formState, readFormStateRef.current, true)) {
|
1676
|
+
formStateRef.current = Object.assign(Object.assign({}, formStateRef.current), formState);
|
1677
|
+
updateFormState(formStateRef.current);
|
1687
1678
|
}
|
1688
1679
|
},
|
1689
1680
|
});
|
1690
|
-
const useFieldArraySubscription =
|
1681
|
+
const useFieldArraySubscription = subjectsRef.current.array.subscribe({
|
1691
1682
|
next(state) {
|
1692
|
-
if (state.values && state.name &&
|
1693
|
-
|
1694
|
-
|
1683
|
+
if (state.values && state.name && readFormStateRef.current.isValid) {
|
1684
|
+
const values = getFieldsValues(fieldsRef);
|
1685
|
+
set(values, state.name, state.values);
|
1686
|
+
updateIsValid(values);
|
1695
1687
|
}
|
1696
1688
|
},
|
1697
1689
|
});
|
@@ -1699,49 +1691,82 @@ function useForm(props = {}) {
|
|
1699
1691
|
formStateSubscription.unsubscribe();
|
1700
1692
|
useFieldArraySubscription.unsubscribe();
|
1701
1693
|
};
|
1702
|
-
}, [
|
1694
|
+
}, []);
|
1703
1695
|
React.useEffect(() => {
|
1704
1696
|
const unregisterFieldNames = [];
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
}
|
1711
|
-
for (const name of
|
1712
|
-
const field = get(
|
1697
|
+
const isLiveInDom = (ref) => !isHTMLElement(ref) || !document.contains(ref);
|
1698
|
+
if (!isMountedRef.current) {
|
1699
|
+
isMountedRef.current = true;
|
1700
|
+
readFormStateRef.current.isValid && updateIsValid();
|
1701
|
+
!shouldUnregister && registerAbsentFields(defaultValuesRef.current);
|
1702
|
+
}
|
1703
|
+
for (const name of namesRef.current.unMount) {
|
1704
|
+
const field = get(fieldsRef.current, name);
|
1713
1705
|
field &&
|
1714
|
-
(field._f.refs
|
1706
|
+
(field._f.refs
|
1707
|
+
? field._f.refs.every(isLiveInDom)
|
1708
|
+
: isLiveInDom(field._f.ref)) &&
|
1715
1709
|
unregisterFieldNames.push(name);
|
1716
1710
|
}
|
1717
1711
|
unregisterFieldNames.length &&
|
1718
|
-
|
1719
|
-
|
1712
|
+
unregister(unregisterFieldNames);
|
1713
|
+
namesRef.current.unMount = new Set();
|
1720
1714
|
});
|
1721
|
-
return
|
1715
|
+
return {
|
1716
|
+
control: React.useMemo(() => ({
|
1717
|
+
register,
|
1718
|
+
inFieldArrayActionRef,
|
1719
|
+
getIsDirty,
|
1720
|
+
subjectsRef,
|
1721
|
+
watchInternal,
|
1722
|
+
fieldsRef,
|
1723
|
+
updateIsValid,
|
1724
|
+
namesRef,
|
1725
|
+
readFormStateRef,
|
1726
|
+
formStateRef,
|
1727
|
+
defaultValuesRef,
|
1728
|
+
fieldArrayDefaultValuesRef,
|
1729
|
+
setValues,
|
1730
|
+
unregister,
|
1731
|
+
shouldUnmount: shouldUnregister,
|
1732
|
+
}), []),
|
1733
|
+
formState: getProxyFormState(isProxyEnabled, formState, readFormStateRef),
|
1734
|
+
trigger,
|
1735
|
+
register,
|
1736
|
+
handleSubmit,
|
1737
|
+
watch: React.useCallback(watch, []),
|
1738
|
+
setValue: React.useCallback(setValue, [setValues]),
|
1739
|
+
getValues: React.useCallback(getValues, []),
|
1740
|
+
reset: React.useCallback(reset, []),
|
1741
|
+
clearErrors: React.useCallback(clearErrors, []),
|
1742
|
+
unregister: React.useCallback(unregister, []),
|
1743
|
+
setError: React.useCallback(setError, []),
|
1744
|
+
setFocus: React.useCallback(setFocus, []),
|
1745
|
+
};
|
1722
1746
|
}
|
1723
1747
|
|
1724
1748
|
function useWatch(props) {
|
1749
|
+
const { control, name, defaultValue } = props || {};
|
1725
1750
|
const methods = useFormContext();
|
1726
|
-
const
|
1727
|
-
|
1728
|
-
|
1751
|
+
const nameRef = React.useRef(name);
|
1752
|
+
nameRef.current = name;
|
1753
|
+
const { watchInternal, subjectsRef } = control || methods.control;
|
1729
1754
|
const [value, updateValue] = React.useState(isUndefined(defaultValue)
|
1730
|
-
?
|
1755
|
+
? watchInternal(name)
|
1731
1756
|
: defaultValue);
|
1732
1757
|
React.useEffect(() => {
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1758
|
+
watchInternal(name);
|
1759
|
+
const watchSubscription = subjectsRef.current.watch.subscribe({
|
1760
|
+
next: ({ name: inputName, values }) => (!nameRef.current ||
|
1761
|
+
!inputName ||
|
1762
|
+
convertToArrayPayload(nameRef.current).some((fieldName) => inputName &&
|
1737
1763
|
fieldName &&
|
1738
|
-
(fieldName.startsWith(
|
1739
|
-
|
1740
|
-
updateValue(
|
1764
|
+
(fieldName.startsWith(inputName) ||
|
1765
|
+
inputName.startsWith(fieldName)))) &&
|
1766
|
+
updateValue(watchInternal(nameRef.current, defaultValue, false, values)),
|
1741
1767
|
});
|
1742
|
-
disabled && watchSubscription.unsubscribe();
|
1743
1768
|
return () => watchSubscription.unsubscribe();
|
1744
|
-
}, [
|
1769
|
+
}, []);
|
1745
1770
|
return value;
|
1746
1771
|
}
|
1747
1772
|
|