react-hook-form 7.54.1 → 7.55.0-next.0
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/README.md +3 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.mjs +1601 -1594
- package/dist/index.esm.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/createFormControl.d.ts +3 -1
- package/dist/logic/createFormControl.d.ts.map +1 -1
- package/dist/logic/getFieldValue.d.ts.map +1 -1
- package/dist/logic/index.d.ts +2 -1
- package/dist/logic/index.d.ts.map +1 -1
- package/dist/logic/shouldRenderFormState.d.ts +3 -2
- package/dist/logic/shouldRenderFormState.d.ts.map +1 -1
- package/dist/logic/validateField.d.ts +2 -2
- package/dist/logic/validateField.d.ts.map +1 -1
- package/dist/react-server.esm.mjs +1727 -4
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/form.d.ts +50 -11
- package/dist/types/form.d.ts.map +1 -1
- package/dist/useController.d.ts.map +1 -1
- package/dist/useFieldArray.d.ts.map +1 -1
- package/dist/useForm.d.ts.map +1 -1
- package/dist/useFormState.d.ts.map +1 -1
- package/dist/useWatch.d.ts.map +1 -1
- package/dist/utils/omit.d.ts +3 -0
- package/dist/utils/omit.d.ts.map +1 -0
- package/package.json +22 -21
- package/dist/useSubscribe.d.ts +0 -9
- package/dist/useSubscribe.d.ts.map +0 -1
package/dist/index.esm.mjs
CHANGED
@@ -217,43 +217,6 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
|
|
217
217
|
return result;
|
218
218
|
};
|
219
219
|
|
220
|
-
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
221
|
-
|
222
|
-
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
223
|
-
updateFormState(formStateData);
|
224
|
-
const { name, ...formState } = formStateData;
|
225
|
-
return (isEmptyObject(formState) ||
|
226
|
-
Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
|
227
|
-
Object.keys(formState).find((key) => _proxyFormState[key] ===
|
228
|
-
(!isRoot || VALIDATION_MODE.all)));
|
229
|
-
};
|
230
|
-
|
231
|
-
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
232
|
-
|
233
|
-
var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
234
|
-
!signalName ||
|
235
|
-
name === signalName ||
|
236
|
-
convertToArrayPayload(name).some((currentName) => currentName &&
|
237
|
-
(exact
|
238
|
-
? currentName === signalName
|
239
|
-
: currentName.startsWith(signalName) ||
|
240
|
-
signalName.startsWith(currentName)));
|
241
|
-
|
242
|
-
function useSubscribe(props) {
|
243
|
-
const _props = React.useRef(props);
|
244
|
-
_props.current = props;
|
245
|
-
React.useEffect(() => {
|
246
|
-
const subscription = !props.disabled &&
|
247
|
-
_props.current.subject &&
|
248
|
-
_props.current.subject.subscribe({
|
249
|
-
next: _props.current.next,
|
250
|
-
});
|
251
|
-
return () => {
|
252
|
-
subscription && subscription.unsubscribe();
|
253
|
-
};
|
254
|
-
}, [props.disabled]);
|
255
|
-
}
|
256
|
-
|
257
220
|
/**
|
258
221
|
* This custom hook allows you to subscribe to each form state, and isolate the re-render at the custom hook level. It has its scope in terms of form state subscription, so it would not affect other useFormState and useForm. Using this hook can reduce the re-render impact on large and complex form application.
|
259
222
|
*
|
@@ -288,7 +251,6 @@ function useFormState(props) {
|
|
288
251
|
const methods = useFormContext();
|
289
252
|
const { control = methods.control, disabled, name, exact } = props || {};
|
290
253
|
const [formState, updateFormState] = React.useState(control._formState);
|
291
|
-
const _mounted = React.useRef(true);
|
292
254
|
const _localProxyFormState = React.useRef({
|
293
255
|
isDirty: false,
|
294
256
|
isLoading: false,
|
@@ -301,23 +263,20 @@ function useFormState(props) {
|
|
301
263
|
});
|
302
264
|
const _name = React.useRef(name);
|
303
265
|
_name.current = name;
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
266
|
+
React.useEffect(() => control._subscribe({
|
267
|
+
name: _name.current,
|
268
|
+
formState: _localProxyFormState.current,
|
269
|
+
exact,
|
270
|
+
callback: (formState) => {
|
271
|
+
!disabled &&
|
272
|
+
updateFormState({
|
273
|
+
...control._formState,
|
274
|
+
...formState,
|
275
|
+
});
|
276
|
+
},
|
277
|
+
}), [control, disabled, exact]);
|
315
278
|
React.useEffect(() => {
|
316
|
-
|
317
|
-
_localProxyFormState.current.isValid && control._updateValid(true);
|
318
|
-
return () => {
|
319
|
-
_mounted.current = false;
|
320
|
-
};
|
279
|
+
_localProxyFormState.current.isValid && control._setValid(true);
|
321
280
|
}, [control]);
|
322
281
|
return React.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
|
323
282
|
}
|
@@ -357,15 +316,15 @@ function useWatch(props) {
|
|
357
316
|
const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
|
358
317
|
const _name = React.useRef(name);
|
359
318
|
_name.current = name;
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
if (shouldSubscribeByName(_name.current, formState.name, exact)) {
|
365
|
-
updateValue(cloneObject(generateWatchOutput(_name.current, control._names, formState.values || control._formValues, false, defaultValue)));
|
366
|
-
}
|
319
|
+
React.useEffect(() => control._subscribe({
|
320
|
+
name: _name.current,
|
321
|
+
formState: {
|
322
|
+
values: true,
|
367
323
|
},
|
368
|
-
|
324
|
+
exact,
|
325
|
+
callback: (formState) => !disabled &&
|
326
|
+
updateValue(cloneObject(generateWatchOutput(_name.current, control._names, formState.values || control._formValues, false, defaultValue))),
|
327
|
+
}), [control, defaultValue, disabled, exact]);
|
369
328
|
const [value, updateValue] = React.useState(control._getWatch(name, defaultValue));
|
370
329
|
React.useEffect(() => control._removeUnmounted());
|
371
330
|
return value;
|
@@ -492,6 +451,7 @@ function useController(props) {
|
|
492
451
|
set(control._formValues, name, value);
|
493
452
|
}
|
494
453
|
}
|
454
|
+
!isArrayField && control.register(name);
|
495
455
|
return () => {
|
496
456
|
(isArrayField
|
497
457
|
? _shouldUnregisterField && !control._state.action
|
@@ -501,14 +461,11 @@ function useController(props) {
|
|
501
461
|
};
|
502
462
|
}, [name, control, isArrayField, shouldUnregister]);
|
503
463
|
React.useEffect(() => {
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
value: get(control._fields, name)._f.value,
|
510
|
-
});
|
511
|
-
}
|
464
|
+
control._setDisabledField({
|
465
|
+
disabled,
|
466
|
+
fields: control._fields,
|
467
|
+
name,
|
468
|
+
});
|
512
469
|
}, [disabled, name, control]);
|
513
470
|
return React.useMemo(() => ({
|
514
471
|
field,
|
@@ -686,67 +643,70 @@ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => va
|
|
686
643
|
}
|
687
644
|
: {};
|
688
645
|
|
689
|
-
var
|
690
|
-
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
|
691
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
692
|
-
const r = (Math.random() * 16 + d) % 16 | 0;
|
693
|
-
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
694
|
-
});
|
695
|
-
};
|
696
|
-
|
697
|
-
var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
|
698
|
-
? options.focusName ||
|
699
|
-
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
700
|
-
: '';
|
646
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
701
647
|
|
702
|
-
var
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
}
|
648
|
+
var createSubject = () => {
|
649
|
+
let _observers = [];
|
650
|
+
const next = (value) => {
|
651
|
+
for (const observer of _observers) {
|
652
|
+
observer.next && observer.next(value);
|
653
|
+
}
|
654
|
+
};
|
655
|
+
const subscribe = (observer) => {
|
656
|
+
_observers.push(observer);
|
657
|
+
return {
|
658
|
+
unsubscribe: () => {
|
659
|
+
_observers = _observers.filter((o) => o !== observer);
|
660
|
+
},
|
661
|
+
};
|
662
|
+
};
|
663
|
+
const unsubscribe = () => {
|
664
|
+
_observers = [];
|
665
|
+
};
|
666
|
+
return {
|
667
|
+
get observers() {
|
668
|
+
return _observers;
|
669
|
+
},
|
670
|
+
next,
|
671
|
+
subscribe,
|
672
|
+
unsubscribe,
|
673
|
+
};
|
674
|
+
};
|
709
675
|
|
710
|
-
var
|
711
|
-
(_names.watchAll ||
|
712
|
-
_names.watch.has(name) ||
|
713
|
-
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
|
714
|
-
/^\.\w+/.test(name.slice(watchName.length))));
|
676
|
+
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
715
677
|
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
678
|
+
function deepEqual(object1, object2) {
|
679
|
+
if (isPrimitive(object1) || isPrimitive(object2)) {
|
680
|
+
return object1 === object2;
|
681
|
+
}
|
682
|
+
if (isDateObject(object1) && isDateObject(object2)) {
|
683
|
+
return object1.getTime() === object2.getTime();
|
684
|
+
}
|
685
|
+
const keys1 = Object.keys(object1);
|
686
|
+
const keys2 = Object.keys(object2);
|
687
|
+
if (keys1.length !== keys2.length) {
|
688
|
+
return false;
|
689
|
+
}
|
690
|
+
for (const key of keys1) {
|
691
|
+
const val1 = object1[key];
|
692
|
+
if (!keys2.includes(key)) {
|
693
|
+
return false;
|
694
|
+
}
|
695
|
+
if (key !== 'ref') {
|
696
|
+
const val2 = object2[key];
|
697
|
+
if ((isDateObject(val1) && isDateObject(val2)) ||
|
698
|
+
(isObject(val1) && isObject(val2)) ||
|
699
|
+
(Array.isArray(val1) && Array.isArray(val2))
|
700
|
+
? !deepEqual(val1, val2)
|
701
|
+
: val1 !== val2) {
|
702
|
+
return false;
|
738
703
|
}
|
739
704
|
}
|
740
705
|
}
|
741
|
-
return;
|
742
|
-
}
|
706
|
+
return true;
|
707
|
+
}
|
743
708
|
|
744
|
-
var
|
745
|
-
const fieldArrayErrors = convertToArrayPayload(get(errors, name));
|
746
|
-
set(fieldArrayErrors, 'root', error[name]);
|
747
|
-
set(errors, name, fieldArrayErrors);
|
748
|
-
return errors;
|
749
|
-
};
|
709
|
+
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
750
710
|
|
751
711
|
var isFileInput = (element) => element.type === 'file';
|
752
712
|
|
@@ -761,11 +721,99 @@ var isHTMLElement = (value) => {
|
|
761
721
|
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
|
762
722
|
};
|
763
723
|
|
764
|
-
var
|
724
|
+
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
765
725
|
|
766
726
|
var isRadioInput = (element) => element.type === 'radio';
|
767
727
|
|
768
|
-
var
|
728
|
+
var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
729
|
+
|
730
|
+
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
731
|
+
|
732
|
+
function baseGet(object, updatePath) {
|
733
|
+
const length = updatePath.slice(0, -1).length;
|
734
|
+
let index = 0;
|
735
|
+
while (index < length) {
|
736
|
+
object = isUndefined(object) ? index++ : object[updatePath[index++]];
|
737
|
+
}
|
738
|
+
return object;
|
739
|
+
}
|
740
|
+
function isEmptyArray(obj) {
|
741
|
+
for (const key in obj) {
|
742
|
+
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
743
|
+
return false;
|
744
|
+
}
|
745
|
+
}
|
746
|
+
return true;
|
747
|
+
}
|
748
|
+
function unset(object, path) {
|
749
|
+
const paths = Array.isArray(path)
|
750
|
+
? path
|
751
|
+
: isKey(path)
|
752
|
+
? [path]
|
753
|
+
: stringToPath(path);
|
754
|
+
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
755
|
+
const index = paths.length - 1;
|
756
|
+
const key = paths[index];
|
757
|
+
if (childObject) {
|
758
|
+
delete childObject[key];
|
759
|
+
}
|
760
|
+
if (index !== 0 &&
|
761
|
+
((isObject(childObject) && isEmptyObject(childObject)) ||
|
762
|
+
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
763
|
+
unset(object, paths.slice(0, -1));
|
764
|
+
}
|
765
|
+
return object;
|
766
|
+
}
|
767
|
+
|
768
|
+
var objectHasFunction = (data) => {
|
769
|
+
for (const key in data) {
|
770
|
+
if (isFunction(data[key])) {
|
771
|
+
return true;
|
772
|
+
}
|
773
|
+
}
|
774
|
+
return false;
|
775
|
+
};
|
776
|
+
|
777
|
+
function markFieldsDirty(data, fields = {}) {
|
778
|
+
const isParentNodeArray = Array.isArray(data);
|
779
|
+
if (isObject(data) || isParentNodeArray) {
|
780
|
+
for (const key in data) {
|
781
|
+
if (Array.isArray(data[key]) ||
|
782
|
+
(isObject(data[key]) && !objectHasFunction(data[key]))) {
|
783
|
+
fields[key] = Array.isArray(data[key]) ? [] : {};
|
784
|
+
markFieldsDirty(data[key], fields[key]);
|
785
|
+
}
|
786
|
+
else if (!isNullOrUndefined(data[key])) {
|
787
|
+
fields[key] = true;
|
788
|
+
}
|
789
|
+
}
|
790
|
+
}
|
791
|
+
return fields;
|
792
|
+
}
|
793
|
+
function getDirtyFieldsFromDefaultValues(data, formValues, dirtyFieldsFromValues) {
|
794
|
+
const isParentNodeArray = Array.isArray(data);
|
795
|
+
if (isObject(data) || isParentNodeArray) {
|
796
|
+
for (const key in data) {
|
797
|
+
if (Array.isArray(data[key]) ||
|
798
|
+
(isObject(data[key]) && !objectHasFunction(data[key]))) {
|
799
|
+
if (isUndefined(formValues) ||
|
800
|
+
isPrimitive(dirtyFieldsFromValues[key])) {
|
801
|
+
dirtyFieldsFromValues[key] = Array.isArray(data[key])
|
802
|
+
? markFieldsDirty(data[key], [])
|
803
|
+
: { ...markFieldsDirty(data[key]) };
|
804
|
+
}
|
805
|
+
else {
|
806
|
+
getDirtyFieldsFromDefaultValues(data[key], isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
|
807
|
+
}
|
808
|
+
}
|
809
|
+
else {
|
810
|
+
dirtyFieldsFromValues[key] = !deepEqual(data[key], formValues[key]);
|
811
|
+
}
|
812
|
+
}
|
813
|
+
}
|
814
|
+
return dirtyFieldsFromValues;
|
815
|
+
}
|
816
|
+
var getDirtyFields = (defaultValues, formValues) => getDirtyFieldsFromDefaultValues(defaultValues, formValues, markFieldsDirty(formValues));
|
769
817
|
|
770
818
|
const defaultResult = {
|
771
819
|
value: false,
|
@@ -792,19 +840,209 @@ var getCheckboxValue = (options) => {
|
|
792
840
|
return defaultResult;
|
793
841
|
};
|
794
842
|
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
843
|
+
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
844
|
+
? value
|
845
|
+
: valueAsNumber
|
846
|
+
? value === ''
|
847
|
+
? NaN
|
848
|
+
: value
|
849
|
+
? +value
|
850
|
+
: value
|
851
|
+
: valueAsDate && isString(value)
|
852
|
+
? new Date(value)
|
853
|
+
: setValueAs
|
854
|
+
? setValueAs(value)
|
855
|
+
: value;
|
856
|
+
|
857
|
+
const defaultReturn = {
|
858
|
+
isValid: false,
|
859
|
+
value: null,
|
860
|
+
};
|
861
|
+
var getRadioValue = (options) => Array.isArray(options)
|
862
|
+
? options.reduce((previous, option) => option && option.checked && !option.disabled
|
863
|
+
? {
|
864
|
+
isValid: true,
|
865
|
+
value: option.value,
|
804
866
|
}
|
805
867
|
: previous, defaultReturn)
|
806
868
|
: defaultReturn;
|
807
869
|
|
870
|
+
function getFieldValue(_f) {
|
871
|
+
const ref = _f.ref;
|
872
|
+
if (isFileInput(ref)) {
|
873
|
+
return ref.files;
|
874
|
+
}
|
875
|
+
if (isRadioInput(ref)) {
|
876
|
+
return getRadioValue(_f.refs).value;
|
877
|
+
}
|
878
|
+
if (isMultipleSelect(ref)) {
|
879
|
+
return [...ref.selectedOptions].map(({ value }) => value);
|
880
|
+
}
|
881
|
+
if (isCheckBoxInput(ref)) {
|
882
|
+
return getCheckboxValue(_f.refs).value;
|
883
|
+
}
|
884
|
+
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
885
|
+
}
|
886
|
+
|
887
|
+
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
888
|
+
const fields = {};
|
889
|
+
for (const name of fieldsNames) {
|
890
|
+
const field = get(_fields, name);
|
891
|
+
field && set(fields, name, field._f);
|
892
|
+
}
|
893
|
+
return {
|
894
|
+
criteriaMode,
|
895
|
+
names: [...fieldsNames],
|
896
|
+
fields,
|
897
|
+
shouldUseNativeValidation,
|
898
|
+
};
|
899
|
+
};
|
900
|
+
|
901
|
+
var isRegex = (value) => value instanceof RegExp;
|
902
|
+
|
903
|
+
var getRuleValue = (rule) => isUndefined(rule)
|
904
|
+
? rule
|
905
|
+
: isRegex(rule)
|
906
|
+
? rule.source
|
907
|
+
: isObject(rule)
|
908
|
+
? isRegex(rule.value)
|
909
|
+
? rule.value.source
|
910
|
+
: rule.value
|
911
|
+
: rule;
|
912
|
+
|
913
|
+
var getValidationModes = (mode) => ({
|
914
|
+
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
|
915
|
+
isOnBlur: mode === VALIDATION_MODE.onBlur,
|
916
|
+
isOnChange: mode === VALIDATION_MODE.onChange,
|
917
|
+
isOnAll: mode === VALIDATION_MODE.all,
|
918
|
+
isOnTouch: mode === VALIDATION_MODE.onTouched,
|
919
|
+
});
|
920
|
+
|
921
|
+
const ASYNC_FUNCTION = 'AsyncFunction';
|
922
|
+
var hasPromiseValidation = (fieldReference) => !!fieldReference &&
|
923
|
+
!!fieldReference.validate &&
|
924
|
+
!!((isFunction(fieldReference.validate) &&
|
925
|
+
fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
|
926
|
+
(isObject(fieldReference.validate) &&
|
927
|
+
Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
|
928
|
+
|
929
|
+
var hasValidation = (options) => options.mount &&
|
930
|
+
(options.required ||
|
931
|
+
options.min ||
|
932
|
+
options.max ||
|
933
|
+
options.maxLength ||
|
934
|
+
options.minLength ||
|
935
|
+
options.pattern ||
|
936
|
+
options.validate);
|
937
|
+
|
938
|
+
var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
|
939
|
+
(_names.watchAll ||
|
940
|
+
_names.watch.has(name) ||
|
941
|
+
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
|
942
|
+
/^\.\w+/.test(name.slice(watchName.length))));
|
943
|
+
|
944
|
+
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
945
|
+
for (const key of fieldsNames || Object.keys(fields)) {
|
946
|
+
const field = get(fields, key);
|
947
|
+
if (field) {
|
948
|
+
const { _f, ...currentField } = field;
|
949
|
+
if (_f) {
|
950
|
+
if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
|
951
|
+
return true;
|
952
|
+
}
|
953
|
+
else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
|
954
|
+
return true;
|
955
|
+
}
|
956
|
+
else {
|
957
|
+
if (iterateFieldsByAction(currentField, action)) {
|
958
|
+
break;
|
959
|
+
}
|
960
|
+
}
|
961
|
+
}
|
962
|
+
else if (isObject(currentField)) {
|
963
|
+
if (iterateFieldsByAction(currentField, action)) {
|
964
|
+
break;
|
965
|
+
}
|
966
|
+
}
|
967
|
+
}
|
968
|
+
}
|
969
|
+
return;
|
970
|
+
};
|
971
|
+
|
972
|
+
function schemaErrorLookup(errors, _fields, name) {
|
973
|
+
const error = get(errors, name);
|
974
|
+
if (error || isKey(name)) {
|
975
|
+
return {
|
976
|
+
error,
|
977
|
+
name,
|
978
|
+
};
|
979
|
+
}
|
980
|
+
const names = name.split('.');
|
981
|
+
while (names.length) {
|
982
|
+
const fieldName = names.join('.');
|
983
|
+
const field = get(_fields, fieldName);
|
984
|
+
const foundError = get(errors, fieldName);
|
985
|
+
if (field && !Array.isArray(field) && name !== fieldName) {
|
986
|
+
return { name };
|
987
|
+
}
|
988
|
+
if (foundError && foundError.type) {
|
989
|
+
return {
|
990
|
+
name: fieldName,
|
991
|
+
error: foundError,
|
992
|
+
};
|
993
|
+
}
|
994
|
+
names.pop();
|
995
|
+
}
|
996
|
+
return {
|
997
|
+
name,
|
998
|
+
};
|
999
|
+
}
|
1000
|
+
|
1001
|
+
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
1002
|
+
updateFormState(formStateData);
|
1003
|
+
const { name, ...formState } = formStateData;
|
1004
|
+
return (isEmptyObject(formState) ||
|
1005
|
+
Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
|
1006
|
+
Object.keys(formState).find((key) => _proxyFormState[key] ===
|
1007
|
+
(!isRoot || VALIDATION_MODE.all)));
|
1008
|
+
};
|
1009
|
+
|
1010
|
+
var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
1011
|
+
!signalName ||
|
1012
|
+
name === signalName ||
|
1013
|
+
convertToArrayPayload(name).some((currentName) => currentName &&
|
1014
|
+
(exact
|
1015
|
+
? currentName === signalName
|
1016
|
+
: currentName.startsWith(signalName) ||
|
1017
|
+
signalName.startsWith(currentName)));
|
1018
|
+
|
1019
|
+
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
|
1020
|
+
if (mode.isOnAll) {
|
1021
|
+
return false;
|
1022
|
+
}
|
1023
|
+
else if (!isSubmitted && mode.isOnTouch) {
|
1024
|
+
return !(isTouched || isBlurEvent);
|
1025
|
+
}
|
1026
|
+
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
|
1027
|
+
return !isBlurEvent;
|
1028
|
+
}
|
1029
|
+
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
|
1030
|
+
return isBlurEvent;
|
1031
|
+
}
|
1032
|
+
return true;
|
1033
|
+
};
|
1034
|
+
|
1035
|
+
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
1036
|
+
|
1037
|
+
var updateFieldArrayRootError = (errors, error, name) => {
|
1038
|
+
const fieldArrayErrors = convertToArrayPayload(get(errors, name));
|
1039
|
+
set(fieldArrayErrors, 'root', error[name]);
|
1040
|
+
set(errors, name, fieldArrayErrors);
|
1041
|
+
return errors;
|
1042
|
+
};
|
1043
|
+
|
1044
|
+
var isMessage = (value) => isString(value);
|
1045
|
+
|
808
1046
|
function getValidateError(result, ref, type = 'validate') {
|
809
1047
|
if (isMessage(result) ||
|
810
1048
|
(Array.isArray(result) && result.every(isMessage)) ||
|
@@ -824,10 +1062,10 @@ var getValueAndMessage = (validationData) => isObject(validationData) && !isRege
|
|
824
1062
|
message: '',
|
825
1063
|
};
|
826
1064
|
|
827
|
-
var validateField = async (field, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
|
828
|
-
const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount,
|
1065
|
+
var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
|
1066
|
+
const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f;
|
829
1067
|
const inputValue = get(formValues, name);
|
830
|
-
if (!mount ||
|
1068
|
+
if (!mount || disabledFieldNames.has(name)) {
|
831
1069
|
return {};
|
832
1070
|
}
|
833
1071
|
const inputRef = refs ? refs[0] : ref;
|
@@ -1003,1565 +1241,1337 @@ var validateField = async (field, formValues, validateAllFieldCriteria, shouldUs
|
|
1003
1241
|
return error;
|
1004
1242
|
};
|
1005
1243
|
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
|
1012
|
-
|
1013
|
-
function insert(data, index, value) {
|
1014
|
-
return [
|
1015
|
-
...data.slice(0, index),
|
1016
|
-
...convertToArrayPayload(value),
|
1017
|
-
...data.slice(index),
|
1018
|
-
];
|
1019
|
-
}
|
1020
|
-
|
1021
|
-
var moveArrayAt = (data, from, to) => {
|
1022
|
-
if (!Array.isArray(data)) {
|
1023
|
-
return [];
|
1024
|
-
}
|
1025
|
-
if (isUndefined(data[to])) {
|
1026
|
-
data[to] = undefined;
|
1027
|
-
}
|
1028
|
-
data.splice(to, 0, data.splice(from, 1)[0]);
|
1029
|
-
return data;
|
1030
|
-
};
|
1031
|
-
|
1032
|
-
var prependAt = (data, value) => [
|
1033
|
-
...convertToArrayPayload(value),
|
1034
|
-
...convertToArrayPayload(data),
|
1035
|
-
];
|
1036
|
-
|
1037
|
-
function removeAtIndexes(data, indexes) {
|
1038
|
-
let i = 0;
|
1039
|
-
const temp = [...data];
|
1040
|
-
for (const index of indexes) {
|
1041
|
-
temp.splice(index - i, 1);
|
1042
|
-
i++;
|
1043
|
-
}
|
1044
|
-
return compact(temp).length ? temp : [];
|
1045
|
-
}
|
1046
|
-
var removeArrayAt = (data, index) => isUndefined(index)
|
1047
|
-
? []
|
1048
|
-
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
1049
|
-
|
1050
|
-
var swapArrayAt = (data, indexA, indexB) => {
|
1051
|
-
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
1244
|
+
const defaultOptions = {
|
1245
|
+
mode: VALIDATION_MODE.onSubmit,
|
1246
|
+
reValidateMode: VALIDATION_MODE.onChange,
|
1247
|
+
shouldFocusError: true,
|
1052
1248
|
};
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
while (index < length) {
|
1058
|
-
object = isUndefined(object) ? index++ : object[updatePath[index++]];
|
1059
|
-
}
|
1060
|
-
return object;
|
1061
|
-
}
|
1062
|
-
function isEmptyArray(obj) {
|
1063
|
-
for (const key in obj) {
|
1064
|
-
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
1065
|
-
return false;
|
1066
|
-
}
|
1067
|
-
}
|
1068
|
-
return true;
|
1069
|
-
}
|
1070
|
-
function unset(object, path) {
|
1071
|
-
const paths = Array.isArray(path)
|
1072
|
-
? path
|
1073
|
-
: isKey(path)
|
1074
|
-
? [path]
|
1075
|
-
: stringToPath(path);
|
1076
|
-
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
1077
|
-
const index = paths.length - 1;
|
1078
|
-
const key = paths[index];
|
1079
|
-
if (childObject) {
|
1080
|
-
delete childObject[key];
|
1081
|
-
}
|
1082
|
-
if (index !== 0 &&
|
1083
|
-
((isObject(childObject) && isEmptyObject(childObject)) ||
|
1084
|
-
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
1085
|
-
unset(object, paths.slice(0, -1));
|
1086
|
-
}
|
1087
|
-
return object;
|
1088
|
-
}
|
1089
|
-
|
1090
|
-
var updateAt = (fieldValues, index, value) => {
|
1091
|
-
fieldValues[index] = value;
|
1092
|
-
return fieldValues;
|
1093
|
-
};
|
1094
|
-
|
1095
|
-
/**
|
1096
|
-
* A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A)
|
1097
|
-
*
|
1098
|
-
* @remarks
|
1099
|
-
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
1100
|
-
*
|
1101
|
-
* @param props - useFieldArray props
|
1102
|
-
*
|
1103
|
-
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
1104
|
-
*
|
1105
|
-
* @example
|
1106
|
-
* ```tsx
|
1107
|
-
* function App() {
|
1108
|
-
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
1109
|
-
* defaultValues: {
|
1110
|
-
* test: []
|
1111
|
-
* }
|
1112
|
-
* });
|
1113
|
-
* const { fields, append } = useFieldArray({
|
1114
|
-
* control,
|
1115
|
-
* name: "test"
|
1116
|
-
* });
|
1117
|
-
*
|
1118
|
-
* return (
|
1119
|
-
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
1120
|
-
* {fields.map((item, index) => (
|
1121
|
-
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
1122
|
-
* ))}
|
1123
|
-
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
1124
|
-
* append
|
1125
|
-
* </button>
|
1126
|
-
* <input type="submit" />
|
1127
|
-
* </form>
|
1128
|
-
* );
|
1129
|
-
* }
|
1130
|
-
* ```
|
1131
|
-
*/
|
1132
|
-
function useFieldArray(props) {
|
1133
|
-
const methods = useFormContext();
|
1134
|
-
const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
|
1135
|
-
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
1136
|
-
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
1137
|
-
const _fieldIds = React.useRef(fields);
|
1138
|
-
const _name = React.useRef(name);
|
1139
|
-
const _actioned = React.useRef(false);
|
1140
|
-
_name.current = name;
|
1141
|
-
_fieldIds.current = fields;
|
1142
|
-
control._names.array.add(name);
|
1143
|
-
rules &&
|
1144
|
-
control.register(name, rules);
|
1145
|
-
useSubscribe({
|
1146
|
-
next: ({ values, name: fieldArrayName, }) => {
|
1147
|
-
if (fieldArrayName === _name.current || !fieldArrayName) {
|
1148
|
-
const fieldValues = get(values, _name.current);
|
1149
|
-
if (Array.isArray(fieldValues)) {
|
1150
|
-
setFields(fieldValues);
|
1151
|
-
ids.current = fieldValues.map(generateId);
|
1152
|
-
}
|
1153
|
-
}
|
1154
|
-
},
|
1155
|
-
subject: control._subjects.array,
|
1156
|
-
});
|
1157
|
-
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
1158
|
-
_actioned.current = true;
|
1159
|
-
control._updateFieldArray(name, updatedFieldArrayValues);
|
1160
|
-
}, [control, name]);
|
1161
|
-
const append = (value, options) => {
|
1162
|
-
const appendValue = convertToArrayPayload(cloneObject(value));
|
1163
|
-
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
|
1164
|
-
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
|
1165
|
-
ids.current = appendAt(ids.current, appendValue.map(generateId));
|
1166
|
-
updateValues(updatedFieldArrayValues);
|
1167
|
-
setFields(updatedFieldArrayValues);
|
1168
|
-
control._updateFieldArray(name, updatedFieldArrayValues, appendAt, {
|
1169
|
-
argA: fillEmptyArray(value),
|
1170
|
-
});
|
1249
|
+
function createFormControl(props = {}) {
|
1250
|
+
let _options = {
|
1251
|
+
...defaultOptions,
|
1252
|
+
...props,
|
1171
1253
|
};
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
}
|
1254
|
+
let _formState = {
|
1255
|
+
submitCount: 0,
|
1256
|
+
isDirty: false,
|
1257
|
+
isLoading: isFunction(_options.defaultValues),
|
1258
|
+
isValidating: false,
|
1259
|
+
isSubmitted: false,
|
1260
|
+
isSubmitting: false,
|
1261
|
+
isSubmitSuccessful: false,
|
1262
|
+
isValid: false,
|
1263
|
+
touchedFields: {},
|
1264
|
+
dirtyFields: {},
|
1265
|
+
validatingFields: {},
|
1266
|
+
errors: _options.errors || {},
|
1267
|
+
disabled: _options.disabled || false,
|
1182
1268
|
};
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1269
|
+
let _fields = {};
|
1270
|
+
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
|
1271
|
+
? cloneObject(_options.defaultValues || _options.values) || {}
|
1272
|
+
: {};
|
1273
|
+
let _formValues = _options.shouldUnregister
|
1274
|
+
? {}
|
1275
|
+
: cloneObject(_defaultValues);
|
1276
|
+
let _state = {
|
1277
|
+
action: false,
|
1278
|
+
mount: false,
|
1279
|
+
watch: false,
|
1193
1280
|
};
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
setFields(updatedFieldArrayValues);
|
1201
|
-
control._updateFieldArray(name, updatedFieldArrayValues, insert, {
|
1202
|
-
argA: index,
|
1203
|
-
argB: fillEmptyArray(value),
|
1204
|
-
});
|
1281
|
+
let _names = {
|
1282
|
+
mount: new Set(),
|
1283
|
+
disabled: new Set(),
|
1284
|
+
unMount: new Set(),
|
1285
|
+
array: new Set(),
|
1286
|
+
watch: new Set(),
|
1205
1287
|
};
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1288
|
+
let delayErrorCallback;
|
1289
|
+
let timer = 0;
|
1290
|
+
const _proxyFormState = {
|
1291
|
+
isDirty: false,
|
1292
|
+
dirtyFields: false,
|
1293
|
+
validatingFields: false,
|
1294
|
+
touchedFields: false,
|
1295
|
+
isValidating: false,
|
1296
|
+
isValid: false,
|
1297
|
+
errors: false,
|
1216
1298
|
};
|
1217
|
-
|
1218
|
-
|
1219
|
-
moveArrayAt(updatedFieldArrayValues, from, to);
|
1220
|
-
moveArrayAt(ids.current, from, to);
|
1221
|
-
updateValues(updatedFieldArrayValues);
|
1222
|
-
setFields(updatedFieldArrayValues);
|
1223
|
-
control._updateFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
|
1224
|
-
argA: from,
|
1225
|
-
argB: to,
|
1226
|
-
}, false);
|
1299
|
+
let _proxySubscribeFormState = {
|
1300
|
+
..._proxyFormState,
|
1227
1301
|
};
|
1228
|
-
const
|
1229
|
-
|
1230
|
-
|
1231
|
-
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
1232
|
-
updateValues(updatedFieldArrayValues);
|
1233
|
-
setFields([...updatedFieldArrayValues]);
|
1234
|
-
control._updateFieldArray(name, updatedFieldArrayValues, updateAt, {
|
1235
|
-
argA: index,
|
1236
|
-
argB: updateValue,
|
1237
|
-
}, true, false);
|
1302
|
+
const _subjects = {
|
1303
|
+
array: createSubject(),
|
1304
|
+
state: createSubject(),
|
1238
1305
|
};
|
1239
|
-
const
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1306
|
+
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
1307
|
+
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
1308
|
+
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
1309
|
+
const debounce = (callback) => (wait) => {
|
1310
|
+
clearTimeout(timer);
|
1311
|
+
timer = setTimeout(callback, wait);
|
1245
1312
|
};
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
const error = get(result.errors, name);
|
1258
|
-
const existingError = get(control._formState.errors, name);
|
1259
|
-
if (existingError
|
1260
|
-
? (!error && existingError.type) ||
|
1261
|
-
(error &&
|
1262
|
-
(existingError.type !== error.type ||
|
1263
|
-
existingError.message !== error.message))
|
1264
|
-
: error && error.type) {
|
1265
|
-
error
|
1266
|
-
? set(control._formState.errors, name, error)
|
1267
|
-
: unset(control._formState.errors, name);
|
1268
|
-
control._subjects.state.next({
|
1269
|
-
errors: control._formState.errors,
|
1270
|
-
});
|
1271
|
-
}
|
1313
|
+
const _setValid = async (shouldUpdateValid) => {
|
1314
|
+
if (!_options.disabled &&
|
1315
|
+
(_proxyFormState.isValid ||
|
1316
|
+
_proxySubscribeFormState.isValid ||
|
1317
|
+
shouldUpdateValid)) {
|
1318
|
+
const isValid = _options.resolver
|
1319
|
+
? isEmptyObject((await _runSchema()).errors)
|
1320
|
+
: await executeBuiltInValidation(_fields, true);
|
1321
|
+
if (isValid !== _formState.isValid) {
|
1322
|
+
_subjects.state.next({
|
1323
|
+
isValid,
|
1272
1324
|
});
|
1273
1325
|
}
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1326
|
+
}
|
1327
|
+
};
|
1328
|
+
const _updateIsValidating = (names, isValidating) => {
|
1329
|
+
if (!_options.disabled &&
|
1330
|
+
(_proxyFormState.isValidating ||
|
1331
|
+
_proxyFormState.validatingFields ||
|
1332
|
+
_proxySubscribeFormState.isValidating ||
|
1333
|
+
_proxySubscribeFormState.validatingFields)) {
|
1334
|
+
(names || Array.from(_names.mount)).forEach((name) => {
|
1335
|
+
if (name) {
|
1336
|
+
isValidating
|
1337
|
+
? set(_formState.validatingFields, name, isValidating)
|
1338
|
+
: unset(_formState.validatingFields, name);
|
1284
1339
|
}
|
1340
|
+
});
|
1341
|
+
_subjects.state.next({
|
1342
|
+
validatingFields: _formState.validatingFields,
|
1343
|
+
isValidating: !isEmptyObject(_formState.validatingFields),
|
1344
|
+
});
|
1345
|
+
}
|
1346
|
+
};
|
1347
|
+
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
1348
|
+
if (args && method && !_options.disabled) {
|
1349
|
+
_state.action = true;
|
1350
|
+
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
|
1351
|
+
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
1352
|
+
shouldSetValues && set(_fields, name, fieldValues);
|
1353
|
+
}
|
1354
|
+
if (shouldUpdateFieldsAndState &&
|
1355
|
+
Array.isArray(get(_formState.errors, name))) {
|
1356
|
+
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
1357
|
+
shouldSetValues && set(_formState.errors, name, errors);
|
1358
|
+
unsetEmptyArray(_formState.errors, name);
|
1359
|
+
}
|
1360
|
+
if ((_proxyFormState.touchedFields ||
|
1361
|
+
_proxySubscribeFormState.touchedFields) &&
|
1362
|
+
shouldUpdateFieldsAndState &&
|
1363
|
+
Array.isArray(get(_formState.touchedFields, name))) {
|
1364
|
+
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
1365
|
+
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
1285
1366
|
}
|
1367
|
+
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
1368
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
|
1369
|
+
}
|
1370
|
+
_subjects.state.next({
|
1371
|
+
name,
|
1372
|
+
isDirty: _getDirty(name, values),
|
1373
|
+
dirtyFields: _formState.dirtyFields,
|
1374
|
+
errors: _formState.errors,
|
1375
|
+
isValid: _formState.isValid,
|
1376
|
+
});
|
1286
1377
|
}
|
1287
|
-
|
1288
|
-
name,
|
1289
|
-
|
1378
|
+
else {
|
1379
|
+
set(_formValues, name, values);
|
1380
|
+
}
|
1381
|
+
};
|
1382
|
+
const updateErrors = (name, error) => {
|
1383
|
+
set(_formState.errors, name, error);
|
1384
|
+
_subjects.state.next({
|
1385
|
+
errors: _formState.errors,
|
1290
1386
|
});
|
1291
|
-
control._names.focus &&
|
1292
|
-
iterateFieldsByAction(control._fields, (ref, key) => {
|
1293
|
-
if (control._names.focus &&
|
1294
|
-
key.startsWith(control._names.focus) &&
|
1295
|
-
ref.focus) {
|
1296
|
-
ref.focus();
|
1297
|
-
return 1;
|
1298
|
-
}
|
1299
|
-
return;
|
1300
|
-
});
|
1301
|
-
control._names.focus = '';
|
1302
|
-
control._updateValid();
|
1303
|
-
_actioned.current = false;
|
1304
|
-
}, [fields, name, control]);
|
1305
|
-
React.useEffect(() => {
|
1306
|
-
!get(control._formValues, name) && control._updateFieldArray(name);
|
1307
|
-
return () => {
|
1308
|
-
(control._options.shouldUnregister || shouldUnregister) &&
|
1309
|
-
control.unregister(name);
|
1310
|
-
};
|
1311
|
-
}, [name, control, keyName, shouldUnregister]);
|
1312
|
-
return {
|
1313
|
-
swap: React.useCallback(swap, [updateValues, name, control]),
|
1314
|
-
move: React.useCallback(move, [updateValues, name, control]),
|
1315
|
-
prepend: React.useCallback(prepend, [updateValues, name, control]),
|
1316
|
-
append: React.useCallback(append, [updateValues, name, control]),
|
1317
|
-
remove: React.useCallback(remove, [updateValues, name, control]),
|
1318
|
-
insert: React.useCallback(insert$1, [updateValues, name, control]),
|
1319
|
-
update: React.useCallback(update, [updateValues, name, control]),
|
1320
|
-
replace: React.useCallback(replace, [updateValues, name, control]),
|
1321
|
-
fields: React.useMemo(() => fields.map((field, index) => ({
|
1322
|
-
...field,
|
1323
|
-
[keyName]: ids.current[index] || generateId(),
|
1324
|
-
})), [fields, keyName]),
|
1325
1387
|
};
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1388
|
+
const _setErrors = (errors) => {
|
1389
|
+
_formState.errors = errors;
|
1390
|
+
_subjects.state.next({
|
1391
|
+
errors: _formState.errors,
|
1392
|
+
isValid: false,
|
1393
|
+
});
|
1394
|
+
};
|
1395
|
+
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
|
1396
|
+
const field = get(_fields, name);
|
1397
|
+
if (field) {
|
1398
|
+
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
|
1399
|
+
isUndefined(defaultValue) ||
|
1400
|
+
(ref && ref.defaultChecked) ||
|
1401
|
+
shouldSkipSetValueAs
|
1402
|
+
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
1403
|
+
: setFieldValue(name, defaultValue);
|
1404
|
+
_state.mount && _setValid();
|
1333
1405
|
}
|
1334
1406
|
};
|
1335
|
-
const
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
},
|
1407
|
+
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
1408
|
+
let shouldUpdateField = false;
|
1409
|
+
let isPreviousDirty = false;
|
1410
|
+
const output = {
|
1411
|
+
name,
|
1341
1412
|
};
|
1413
|
+
if (!_options.disabled) {
|
1414
|
+
const disabledField = !!(get(_fields, name) &&
|
1415
|
+
get(_fields, name)._f &&
|
1416
|
+
get(_fields, name)._f.disabled);
|
1417
|
+
if (!isBlurEvent || shouldDirty) {
|
1418
|
+
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
1419
|
+
isPreviousDirty = _formState.isDirty;
|
1420
|
+
_formState.isDirty = output.isDirty = _getDirty();
|
1421
|
+
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
1422
|
+
}
|
1423
|
+
const isCurrentFieldPristine = disabledField || deepEqual(get(_defaultValues, name), fieldValue);
|
1424
|
+
isPreviousDirty = !!(!disabledField && get(_formState.dirtyFields, name));
|
1425
|
+
isCurrentFieldPristine || disabledField
|
1426
|
+
? unset(_formState.dirtyFields, name)
|
1427
|
+
: set(_formState.dirtyFields, name, true);
|
1428
|
+
output.dirtyFields = _formState.dirtyFields;
|
1429
|
+
shouldUpdateField =
|
1430
|
+
shouldUpdateField ||
|
1431
|
+
((_proxyFormState.dirtyFields ||
|
1432
|
+
_proxySubscribeFormState.dirtyFields) &&
|
1433
|
+
isPreviousDirty !== !isCurrentFieldPristine);
|
1434
|
+
}
|
1435
|
+
if (isBlurEvent) {
|
1436
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1437
|
+
if (!isPreviousFieldTouched) {
|
1438
|
+
set(_formState.touchedFields, name, isBlurEvent);
|
1439
|
+
output.touchedFields = _formState.touchedFields;
|
1440
|
+
shouldUpdateField =
|
1441
|
+
shouldUpdateField ||
|
1442
|
+
((_proxyFormState.touchedFields ||
|
1443
|
+
_proxySubscribeFormState.touchedFields) &&
|
1444
|
+
isPreviousFieldTouched !== isBlurEvent);
|
1445
|
+
}
|
1446
|
+
}
|
1447
|
+
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
1448
|
+
}
|
1449
|
+
return shouldUpdateField ? output : {};
|
1342
1450
|
};
|
1343
|
-
const
|
1344
|
-
|
1451
|
+
const shouldRenderByError = (name, isValid, error, fieldState) => {
|
1452
|
+
const previousFieldError = get(_formState.errors, name);
|
1453
|
+
const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
1454
|
+
isBoolean(isValid) &&
|
1455
|
+
_formState.isValid !== isValid;
|
1456
|
+
if (_options.delayError && error) {
|
1457
|
+
delayErrorCallback = debounce(() => updateErrors(name, error));
|
1458
|
+
delayErrorCallback(_options.delayError);
|
1459
|
+
}
|
1460
|
+
else {
|
1461
|
+
clearTimeout(timer);
|
1462
|
+
delayErrorCallback = null;
|
1463
|
+
error
|
1464
|
+
? set(_formState.errors, name, error)
|
1465
|
+
: unset(_formState.errors, name);
|
1466
|
+
}
|
1467
|
+
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
1468
|
+
!isEmptyObject(fieldState) ||
|
1469
|
+
shouldUpdateValid) {
|
1470
|
+
const updatedFormState = {
|
1471
|
+
...fieldState,
|
1472
|
+
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
1473
|
+
errors: _formState.errors,
|
1474
|
+
name,
|
1475
|
+
};
|
1476
|
+
_formState = {
|
1477
|
+
..._formState,
|
1478
|
+
...updatedFormState,
|
1479
|
+
};
|
1480
|
+
_subjects.state.next(updatedFormState);
|
1481
|
+
}
|
1345
1482
|
};
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
subscribe,
|
1352
|
-
unsubscribe,
|
1483
|
+
const _runSchema = async (name) => {
|
1484
|
+
_updateIsValidating(name, true);
|
1485
|
+
const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
|
1486
|
+
_updateIsValidating(name);
|
1487
|
+
return result;
|
1353
1488
|
};
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
if (isDateObject(object1) && isDateObject(object2)) {
|
1363
|
-
return object1.getTime() === object2.getTime();
|
1364
|
-
}
|
1365
|
-
const keys1 = Object.keys(object1);
|
1366
|
-
const keys2 = Object.keys(object2);
|
1367
|
-
if (keys1.length !== keys2.length) {
|
1368
|
-
return false;
|
1369
|
-
}
|
1370
|
-
for (const key of keys1) {
|
1371
|
-
const val1 = object1[key];
|
1372
|
-
if (!keys2.includes(key)) {
|
1373
|
-
return false;
|
1374
|
-
}
|
1375
|
-
if (key !== 'ref') {
|
1376
|
-
const val2 = object2[key];
|
1377
|
-
if ((isDateObject(val1) && isDateObject(val2)) ||
|
1378
|
-
(isObject(val1) && isObject(val2)) ||
|
1379
|
-
(Array.isArray(val1) && Array.isArray(val2))
|
1380
|
-
? !deepEqual(val1, val2)
|
1381
|
-
: val1 !== val2) {
|
1382
|
-
return false;
|
1489
|
+
const executeSchemaAndUpdateState = async (names) => {
|
1490
|
+
const { errors } = await _runSchema(names);
|
1491
|
+
if (names) {
|
1492
|
+
for (const name of names) {
|
1493
|
+
const error = get(errors, name);
|
1494
|
+
error
|
1495
|
+
? set(_formState.errors, name, error)
|
1496
|
+
: unset(_formState.errors, name);
|
1383
1497
|
}
|
1384
1498
|
}
|
1385
|
-
|
1386
|
-
|
1387
|
-
}
|
1388
|
-
|
1389
|
-
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
1390
|
-
|
1391
|
-
var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
1392
|
-
|
1393
|
-
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
1394
|
-
|
1395
|
-
var objectHasFunction = (data) => {
|
1396
|
-
for (const key in data) {
|
1397
|
-
if (isFunction(data[key])) {
|
1398
|
-
return true;
|
1499
|
+
else {
|
1500
|
+
_formState.errors = errors;
|
1399
1501
|
}
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1502
|
+
return errors;
|
1503
|
+
};
|
1504
|
+
const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
|
1505
|
+
valid: true,
|
1506
|
+
}) => {
|
1507
|
+
for (const name in fields) {
|
1508
|
+
const field = fields[name];
|
1509
|
+
if (field) {
|
1510
|
+
const { _f, ...fieldValue } = field;
|
1511
|
+
if (_f) {
|
1512
|
+
const isFieldArrayRoot = _names.array.has(_f.name);
|
1513
|
+
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
|
1514
|
+
if (isPromiseFunction && _proxyFormState.validatingFields) {
|
1515
|
+
_updateIsValidating([name], true);
|
1516
|
+
}
|
1517
|
+
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
|
1518
|
+
if (isPromiseFunction && _proxyFormState.validatingFields) {
|
1519
|
+
_updateIsValidating([name]);
|
1520
|
+
}
|
1521
|
+
if (fieldError[_f.name]) {
|
1522
|
+
context.valid = false;
|
1523
|
+
if (shouldOnlyCheckValid) {
|
1524
|
+
break;
|
1525
|
+
}
|
1526
|
+
}
|
1527
|
+
!shouldOnlyCheckValid &&
|
1528
|
+
(get(fieldError, _f.name)
|
1529
|
+
? isFieldArrayRoot
|
1530
|
+
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
1531
|
+
: set(_formState.errors, _f.name, fieldError[_f.name])
|
1532
|
+
: unset(_formState.errors, _f.name));
|
1533
|
+
}
|
1534
|
+
!isEmptyObject(fieldValue) &&
|
1535
|
+
(await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
|
1415
1536
|
}
|
1416
1537
|
}
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1538
|
+
return context.valid;
|
1539
|
+
};
|
1540
|
+
const _removeUnmounted = () => {
|
1541
|
+
for (const name of _names.unMount) {
|
1542
|
+
const field = get(_fields, name);
|
1543
|
+
field &&
|
1544
|
+
(field._f.refs
|
1545
|
+
? field._f.refs.every((ref) => !live(ref))
|
1546
|
+
: !live(field._f.ref)) &&
|
1547
|
+
unregister(name);
|
1548
|
+
}
|
1549
|
+
_names.unMount = new Set();
|
1550
|
+
};
|
1551
|
+
const _getDirty = (name, data) => !_options.disabled &&
|
1552
|
+
(name && data && set(_formValues, name, data),
|
1553
|
+
!deepEqual(getValues(), _defaultValues));
|
1554
|
+
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
1555
|
+
...(_state.mount
|
1556
|
+
? _formValues
|
1557
|
+
: isUndefined(defaultValue)
|
1558
|
+
? _defaultValues
|
1559
|
+
: isString(names)
|
1560
|
+
? { [names]: defaultValue }
|
1561
|
+
: defaultValue),
|
1562
|
+
}, isGlobal, defaultValue);
|
1563
|
+
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
1564
|
+
const setFieldValue = (name, value, options = {}) => {
|
1565
|
+
const field = get(_fields, name);
|
1566
|
+
let fieldValue = value;
|
1567
|
+
if (field) {
|
1568
|
+
const fieldReference = field._f;
|
1569
|
+
if (fieldReference) {
|
1570
|
+
!fieldReference.disabled &&
|
1571
|
+
set(_formValues, name, getFieldValueAs(value, fieldReference));
|
1572
|
+
fieldValue =
|
1573
|
+
isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
|
1574
|
+
? ''
|
1575
|
+
: value;
|
1576
|
+
if (isMultipleSelect(fieldReference.ref)) {
|
1577
|
+
[...fieldReference.ref.options].forEach((optionRef) => (optionRef.selected = fieldValue.includes(optionRef.value)));
|
1578
|
+
}
|
1579
|
+
else if (fieldReference.refs) {
|
1580
|
+
if (isCheckBoxInput(fieldReference.ref)) {
|
1581
|
+
fieldReference.refs.length > 1
|
1582
|
+
? fieldReference.refs.forEach((checkboxRef) => (!checkboxRef.defaultChecked || !checkboxRef.disabled) &&
|
1583
|
+
(checkboxRef.checked = Array.isArray(fieldValue)
|
1584
|
+
? !!fieldValue.find((data) => data === checkboxRef.value)
|
1585
|
+
: fieldValue === checkboxRef.value))
|
1586
|
+
: fieldReference.refs[0] &&
|
1587
|
+
(fieldReference.refs[0].checked = !!fieldValue);
|
1588
|
+
}
|
1589
|
+
else {
|
1590
|
+
fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
|
1591
|
+
}
|
1592
|
+
}
|
1593
|
+
else if (isFileInput(fieldReference.ref)) {
|
1594
|
+
fieldReference.ref.value = '';
|
1431
1595
|
}
|
1432
1596
|
else {
|
1433
|
-
|
1597
|
+
fieldReference.ref.value = fieldValue;
|
1598
|
+
if (!fieldReference.ref.type) {
|
1599
|
+
_subjects.state.next({
|
1600
|
+
name,
|
1601
|
+
values: { ..._formValues },
|
1602
|
+
});
|
1603
|
+
}
|
1434
1604
|
}
|
1435
1605
|
}
|
1436
|
-
else {
|
1437
|
-
dirtyFieldsFromValues[key] = !deepEqual(data[key], formValues[key]);
|
1438
|
-
}
|
1439
1606
|
}
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
var getDirtyFields = (defaultValues, formValues) => getDirtyFieldsFromDefaultValues(defaultValues, formValues, markFieldsDirty(formValues));
|
1444
|
-
|
1445
|
-
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
1446
|
-
? value
|
1447
|
-
: valueAsNumber
|
1448
|
-
? value === ''
|
1449
|
-
? NaN
|
1450
|
-
: value
|
1451
|
-
? +value
|
1452
|
-
: value
|
1453
|
-
: valueAsDate && isString(value)
|
1454
|
-
? new Date(value)
|
1455
|
-
: setValueAs
|
1456
|
-
? setValueAs(value)
|
1457
|
-
: value;
|
1458
|
-
|
1459
|
-
function getFieldValue(_f) {
|
1460
|
-
const ref = _f.ref;
|
1461
|
-
if (_f.refs ? _f.refs.every((ref) => ref.disabled) : ref.disabled) {
|
1462
|
-
return;
|
1463
|
-
}
|
1464
|
-
if (isFileInput(ref)) {
|
1465
|
-
return ref.files;
|
1466
|
-
}
|
1467
|
-
if (isRadioInput(ref)) {
|
1468
|
-
return getRadioValue(_f.refs).value;
|
1469
|
-
}
|
1470
|
-
if (isMultipleSelect(ref)) {
|
1471
|
-
return [...ref.selectedOptions].map(({ value }) => value);
|
1472
|
-
}
|
1473
|
-
if (isCheckBoxInput(ref)) {
|
1474
|
-
return getCheckboxValue(_f.refs).value;
|
1475
|
-
}
|
1476
|
-
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
1477
|
-
}
|
1478
|
-
|
1479
|
-
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
1480
|
-
const fields = {};
|
1481
|
-
for (const name of fieldsNames) {
|
1482
|
-
const field = get(_fields, name);
|
1483
|
-
field && set(fields, name, field._f);
|
1484
|
-
}
|
1485
|
-
return {
|
1486
|
-
criteriaMode,
|
1487
|
-
names: [...fieldsNames],
|
1488
|
-
fields,
|
1489
|
-
shouldUseNativeValidation,
|
1607
|
+
(options.shouldDirty || options.shouldTouch) &&
|
1608
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
|
1609
|
+
options.shouldValidate && trigger(name);
|
1490
1610
|
};
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
const ASYNC_FUNCTION = 'AsyncFunction';
|
1504
|
-
var hasPromiseValidation = (fieldReference) => !!fieldReference &&
|
1505
|
-
!!fieldReference.validate &&
|
1506
|
-
!!((isFunction(fieldReference.validate) &&
|
1507
|
-
fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
|
1508
|
-
(isObject(fieldReference.validate) &&
|
1509
|
-
Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
|
1510
|
-
|
1511
|
-
var hasValidation = (options) => options.mount &&
|
1512
|
-
(options.required ||
|
1513
|
-
options.min ||
|
1514
|
-
options.max ||
|
1515
|
-
options.maxLength ||
|
1516
|
-
options.minLength ||
|
1517
|
-
options.pattern ||
|
1518
|
-
options.validate);
|
1519
|
-
|
1520
|
-
function schemaErrorLookup(errors, _fields, name) {
|
1521
|
-
const error = get(errors, name);
|
1522
|
-
if (error || isKey(name)) {
|
1523
|
-
return {
|
1524
|
-
error,
|
1525
|
-
name,
|
1526
|
-
};
|
1527
|
-
}
|
1528
|
-
const names = name.split('.');
|
1529
|
-
while (names.length) {
|
1530
|
-
const fieldName = names.join('.');
|
1531
|
-
const field = get(_fields, fieldName);
|
1532
|
-
const foundError = get(errors, fieldName);
|
1533
|
-
if (field && !Array.isArray(field) && name !== fieldName) {
|
1534
|
-
return { name };
|
1535
|
-
}
|
1536
|
-
if (foundError && foundError.type) {
|
1537
|
-
return {
|
1538
|
-
name: fieldName,
|
1539
|
-
error: foundError,
|
1540
|
-
};
|
1611
|
+
const setValues = (name, value, options) => {
|
1612
|
+
for (const fieldKey in value) {
|
1613
|
+
const fieldValue = value[fieldKey];
|
1614
|
+
const fieldName = `${name}.${fieldKey}`;
|
1615
|
+
const field = get(_fields, fieldName);
|
1616
|
+
(_names.array.has(name) ||
|
1617
|
+
isObject(fieldValue) ||
|
1618
|
+
(field && !field._f)) &&
|
1619
|
+
!isDateObject(fieldValue)
|
1620
|
+
? setValues(fieldName, fieldValue, options)
|
1621
|
+
: setFieldValue(fieldName, fieldValue, options);
|
1541
1622
|
}
|
1542
|
-
names.pop();
|
1543
|
-
}
|
1544
|
-
return {
|
1545
|
-
name,
|
1546
1623
|
};
|
1547
|
-
}
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
return true;
|
1563
|
-
};
|
1564
|
-
|
1565
|
-
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
1566
|
-
|
1567
|
-
const defaultOptions = {
|
1568
|
-
mode: VALIDATION_MODE.onSubmit,
|
1569
|
-
reValidateMode: VALIDATION_MODE.onChange,
|
1570
|
-
shouldFocusError: true,
|
1571
|
-
};
|
1572
|
-
function createFormControl(props = {}) {
|
1573
|
-
let _options = {
|
1574
|
-
...defaultOptions,
|
1575
|
-
...props,
|
1576
|
-
};
|
1577
|
-
let _formState = {
|
1578
|
-
submitCount: 0,
|
1579
|
-
isDirty: false,
|
1580
|
-
isLoading: isFunction(_options.defaultValues),
|
1581
|
-
isValidating: false,
|
1582
|
-
isSubmitted: false,
|
1583
|
-
isSubmitting: false,
|
1584
|
-
isSubmitSuccessful: false,
|
1585
|
-
isValid: false,
|
1586
|
-
touchedFields: {},
|
1587
|
-
dirtyFields: {},
|
1588
|
-
validatingFields: {},
|
1589
|
-
errors: _options.errors || {},
|
1590
|
-
disabled: _options.disabled || false,
|
1591
|
-
};
|
1592
|
-
let _fields = {};
|
1593
|
-
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
|
1594
|
-
? cloneObject(_options.defaultValues || _options.values) || {}
|
1595
|
-
: {};
|
1596
|
-
let _formValues = _options.shouldUnregister
|
1597
|
-
? {}
|
1598
|
-
: cloneObject(_defaultValues);
|
1599
|
-
let _state = {
|
1600
|
-
action: false,
|
1601
|
-
mount: false,
|
1602
|
-
watch: false,
|
1603
|
-
};
|
1604
|
-
let _names = {
|
1605
|
-
mount: new Set(),
|
1606
|
-
unMount: new Set(),
|
1607
|
-
array: new Set(),
|
1608
|
-
watch: new Set(),
|
1609
|
-
};
|
1610
|
-
let delayErrorCallback;
|
1611
|
-
let timer = 0;
|
1612
|
-
const _proxyFormState = {
|
1613
|
-
isDirty: false,
|
1614
|
-
dirtyFields: false,
|
1615
|
-
validatingFields: false,
|
1616
|
-
touchedFields: false,
|
1617
|
-
isValidating: false,
|
1618
|
-
isValid: false,
|
1619
|
-
errors: false,
|
1620
|
-
};
|
1621
|
-
const _subjects = {
|
1622
|
-
values: createSubject(),
|
1623
|
-
array: createSubject(),
|
1624
|
-
state: createSubject(),
|
1625
|
-
};
|
1626
|
-
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
1627
|
-
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
1628
|
-
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
1629
|
-
const debounce = (callback) => (wait) => {
|
1630
|
-
clearTimeout(timer);
|
1631
|
-
timer = setTimeout(callback, wait);
|
1632
|
-
};
|
1633
|
-
const _updateValid = async (shouldUpdateValid) => {
|
1634
|
-
if (!_options.disabled && (_proxyFormState.isValid || shouldUpdateValid)) {
|
1635
|
-
const isValid = _options.resolver
|
1636
|
-
? isEmptyObject((await _executeSchema()).errors)
|
1637
|
-
: await executeBuiltInValidation(_fields, true);
|
1638
|
-
if (isValid !== _formState.isValid) {
|
1624
|
+
const setValue = (name, value, options = {}) => {
|
1625
|
+
const field = get(_fields, name);
|
1626
|
+
const isFieldArray = _names.array.has(name);
|
1627
|
+
const cloneValue = cloneObject(value);
|
1628
|
+
set(_formValues, name, cloneValue);
|
1629
|
+
if (isFieldArray) {
|
1630
|
+
_subjects.array.next({
|
1631
|
+
name,
|
1632
|
+
values: { ..._formValues },
|
1633
|
+
});
|
1634
|
+
if ((_proxyFormState.isDirty ||
|
1635
|
+
_proxyFormState.dirtyFields ||
|
1636
|
+
_proxySubscribeFormState.isDirty ||
|
1637
|
+
_proxySubscribeFormState.dirtyFields) &&
|
1638
|
+
options.shouldDirty) {
|
1639
1639
|
_subjects.state.next({
|
1640
|
-
|
1640
|
+
name,
|
1641
|
+
dirtyFields: getDirtyFields(_defaultValues, _formValues),
|
1642
|
+
isDirty: _getDirty(name, cloneValue),
|
1641
1643
|
});
|
1642
1644
|
}
|
1643
1645
|
}
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
(names || Array.from(_names.mount)).forEach((name) => {
|
1649
|
-
if (name) {
|
1650
|
-
isValidating
|
1651
|
-
? set(_formState.validatingFields, name, isValidating)
|
1652
|
-
: unset(_formState.validatingFields, name);
|
1653
|
-
}
|
1654
|
-
});
|
1655
|
-
_subjects.state.next({
|
1656
|
-
validatingFields: _formState.validatingFields,
|
1657
|
-
isValidating: !isEmptyObject(_formState.validatingFields),
|
1658
|
-
});
|
1646
|
+
else {
|
1647
|
+
field && !field._f && !isNullOrUndefined(cloneValue)
|
1648
|
+
? setValues(name, cloneValue, options)
|
1649
|
+
: setFieldValue(name, cloneValue, options);
|
1659
1650
|
}
|
1651
|
+
isWatched(name, _names) && _subjects.state.next({ ..._formState });
|
1652
|
+
_subjects.state.next({
|
1653
|
+
name: _state.mount ? name : undefined,
|
1654
|
+
values: { ..._formValues },
|
1655
|
+
});
|
1660
1656
|
};
|
1661
|
-
const
|
1662
|
-
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1657
|
+
const onChange = async (event) => {
|
1658
|
+
_state.mount = true;
|
1659
|
+
const target = event.target;
|
1660
|
+
let name = target.name;
|
1661
|
+
let isFieldValueUpdated = true;
|
1662
|
+
const field = get(_fields, name);
|
1663
|
+
const _updateIsFieldValueUpdated = (fieldValue) => {
|
1664
|
+
isFieldValueUpdated =
|
1665
|
+
Number.isNaN(fieldValue) ||
|
1666
|
+
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
1667
|
+
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
1668
|
+
};
|
1669
|
+
if (field) {
|
1670
|
+
let error;
|
1671
|
+
let isValid;
|
1672
|
+
const fieldValue = target.type
|
1673
|
+
? getFieldValue(field._f)
|
1674
|
+
: getEventValue(event);
|
1675
|
+
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
1676
|
+
const shouldSkipValidation = (!hasValidation(field._f) &&
|
1677
|
+
!_options.resolver &&
|
1678
|
+
!get(_formState.errors, name) &&
|
1679
|
+
!field._f.deps) ||
|
1680
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
|
1681
|
+
const watched = isWatched(name, _names, isBlurEvent);
|
1682
|
+
set(_formValues, name, fieldValue);
|
1683
|
+
if (isBlurEvent) {
|
1684
|
+
field._f.onBlur && field._f.onBlur(event);
|
1685
|
+
delayErrorCallback && delayErrorCallback(0);
|
1667
1686
|
}
|
1668
|
-
if (
|
1669
|
-
|
1670
|
-
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
1671
|
-
shouldSetValues && set(_formState.errors, name, errors);
|
1672
|
-
unsetEmptyArray(_formState.errors, name);
|
1687
|
+
else if (field._f.onChange) {
|
1688
|
+
field._f.onChange(event);
|
1673
1689
|
}
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1690
|
+
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
|
1691
|
+
const shouldRender = !isEmptyObject(fieldState) || watched;
|
1692
|
+
!isBlurEvent &&
|
1693
|
+
_subjects.state.next({
|
1694
|
+
name,
|
1695
|
+
type: event.type,
|
1696
|
+
values: { ..._formValues },
|
1697
|
+
});
|
1698
|
+
if (shouldSkipValidation) {
|
1699
|
+
if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
|
1700
|
+
if (_options.mode === 'onBlur' && isBlurEvent) {
|
1701
|
+
_setValid();
|
1702
|
+
}
|
1703
|
+
else if (!isBlurEvent) {
|
1704
|
+
_setValid();
|
1705
|
+
}
|
1706
|
+
}
|
1707
|
+
return (shouldRender &&
|
1708
|
+
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
|
1679
1709
|
}
|
1680
|
-
|
1681
|
-
|
1710
|
+
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
|
1711
|
+
if (_options.resolver) {
|
1712
|
+
const { errors } = await _runSchema([name]);
|
1713
|
+
_updateIsFieldValueUpdated(fieldValue);
|
1714
|
+
if (isFieldValueUpdated) {
|
1715
|
+
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
1716
|
+
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
1717
|
+
error = errorLookupResult.error;
|
1718
|
+
name = errorLookupResult.name;
|
1719
|
+
isValid = isEmptyObject(errors);
|
1720
|
+
}
|
1721
|
+
}
|
1722
|
+
else {
|
1723
|
+
_updateIsValidating([name], true);
|
1724
|
+
error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
|
1725
|
+
_updateIsValidating([name]);
|
1726
|
+
_updateIsFieldValueUpdated(fieldValue);
|
1727
|
+
if (isFieldValueUpdated) {
|
1728
|
+
if (error) {
|
1729
|
+
isValid = false;
|
1730
|
+
}
|
1731
|
+
else if (_proxyFormState.isValid ||
|
1732
|
+
_proxySubscribeFormState.isValid) {
|
1733
|
+
isValid = await executeBuiltInValidation(_fields, true);
|
1734
|
+
}
|
1735
|
+
}
|
1736
|
+
}
|
1737
|
+
if (isFieldValueUpdated) {
|
1738
|
+
field._f.deps &&
|
1739
|
+
trigger(field._f.deps);
|
1740
|
+
shouldRenderByError(name, isValid, error, fieldState);
|
1682
1741
|
}
|
1683
|
-
_subjects.state.next({
|
1684
|
-
name,
|
1685
|
-
isDirty: _getDirty(name, values),
|
1686
|
-
dirtyFields: _formState.dirtyFields,
|
1687
|
-
errors: _formState.errors,
|
1688
|
-
isValid: _formState.isValid,
|
1689
|
-
});
|
1690
1742
|
}
|
1691
|
-
|
1692
|
-
|
1743
|
+
};
|
1744
|
+
const _focusInput = (ref, key) => {
|
1745
|
+
if (get(_formState.errors, key) && ref.focus) {
|
1746
|
+
ref.focus();
|
1747
|
+
return 1;
|
1693
1748
|
}
|
1749
|
+
return;
|
1694
1750
|
};
|
1695
|
-
const
|
1696
|
-
|
1751
|
+
const trigger = async (name, options = {}) => {
|
1752
|
+
let isValid;
|
1753
|
+
let validationResult;
|
1754
|
+
const fieldNames = convertToArrayPayload(name);
|
1755
|
+
if (_options.resolver) {
|
1756
|
+
const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
|
1757
|
+
isValid = isEmptyObject(errors);
|
1758
|
+
validationResult = name
|
1759
|
+
? !fieldNames.some((name) => get(errors, name))
|
1760
|
+
: isValid;
|
1761
|
+
}
|
1762
|
+
else if (name) {
|
1763
|
+
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
|
1764
|
+
const field = get(_fields, fieldName);
|
1765
|
+
return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
|
1766
|
+
}))).every(Boolean);
|
1767
|
+
!(!validationResult && !_formState.isValid) && _setValid();
|
1768
|
+
}
|
1769
|
+
else {
|
1770
|
+
validationResult = isValid = await executeBuiltInValidation(_fields);
|
1771
|
+
}
|
1697
1772
|
_subjects.state.next({
|
1773
|
+
...(!isString(name) ||
|
1774
|
+
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
1775
|
+
isValid !== _formState.isValid)
|
1776
|
+
? {}
|
1777
|
+
: { name }),
|
1778
|
+
...(_options.resolver || !name ? { isValid } : {}),
|
1698
1779
|
errors: _formState.errors,
|
1699
1780
|
});
|
1781
|
+
options.shouldFocus &&
|
1782
|
+
!validationResult &&
|
1783
|
+
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
1784
|
+
return validationResult;
|
1700
1785
|
};
|
1701
|
-
const
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1786
|
+
const getValues = (fieldNames) => {
|
1787
|
+
const values = {
|
1788
|
+
...(_state.mount ? _formValues : _defaultValues),
|
1789
|
+
};
|
1790
|
+
return isUndefined(fieldNames)
|
1791
|
+
? values
|
1792
|
+
: isString(fieldNames)
|
1793
|
+
? get(values, fieldNames)
|
1794
|
+
: fieldNames.map((name) => get(values, name));
|
1707
1795
|
};
|
1708
|
-
const
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1796
|
+
const getFieldState = (name, formState) => ({
|
1797
|
+
invalid: !!get((formState || _formState).errors, name),
|
1798
|
+
isDirty: !!get((formState || _formState).dirtyFields, name),
|
1799
|
+
error: get((formState || _formState).errors, name),
|
1800
|
+
isValidating: !!get(_formState.validatingFields, name),
|
1801
|
+
isTouched: !!get((formState || _formState).touchedFields, name),
|
1802
|
+
});
|
1803
|
+
const clearErrors = (name) => {
|
1804
|
+
name &&
|
1805
|
+
convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
|
1806
|
+
_subjects.state.next({
|
1807
|
+
errors: name ? _formState.errors : {},
|
1808
|
+
});
|
1719
1809
|
};
|
1720
|
-
const
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1810
|
+
const setError = (name, error, options) => {
|
1811
|
+
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
1812
|
+
const currentError = get(_formState.errors, name) || {};
|
1813
|
+
// Don't override existing error messages elsewhere in the object tree.
|
1814
|
+
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
1815
|
+
set(_formState.errors, name, {
|
1816
|
+
...restOfErrorTree,
|
1817
|
+
...error,
|
1818
|
+
ref,
|
1819
|
+
});
|
1820
|
+
_subjects.state.next({
|
1724
1821
|
name,
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
:
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
(_proxyFormState.dirtyFields &&
|
1745
|
-
isPreviousDirty !== !isCurrentFieldPristine);
|
1822
|
+
errors: _formState.errors,
|
1823
|
+
isValid: false,
|
1824
|
+
});
|
1825
|
+
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
1826
|
+
};
|
1827
|
+
const watch = (name, defaultValue) => isFunction(name)
|
1828
|
+
? _subjects.state.subscribe({
|
1829
|
+
next: (payload) => name(_getWatch(undefined, defaultValue), payload),
|
1830
|
+
})
|
1831
|
+
: _getWatch(name, defaultValue, true);
|
1832
|
+
const _subscribe = (props) => _subjects.state.subscribe({
|
1833
|
+
next: (formState) => {
|
1834
|
+
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
1835
|
+
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
1836
|
+
props.callback({
|
1837
|
+
values: _formValues,
|
1838
|
+
..._formState,
|
1839
|
+
...formState,
|
1840
|
+
});
|
1746
1841
|
}
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1842
|
+
},
|
1843
|
+
}).unsubscribe;
|
1844
|
+
const subscribe = (props) => {
|
1845
|
+
_state.mount = true;
|
1846
|
+
_proxySubscribeFormState = {
|
1847
|
+
..._proxySubscribeFormState,
|
1848
|
+
...props.formState,
|
1849
|
+
};
|
1850
|
+
return _subscribe({
|
1851
|
+
...props,
|
1852
|
+
formState: _proxySubscribeFormState,
|
1853
|
+
});
|
1854
|
+
};
|
1855
|
+
const unregister = (name, options = {}) => {
|
1856
|
+
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
1857
|
+
_names.mount.delete(fieldName);
|
1858
|
+
_names.array.delete(fieldName);
|
1859
|
+
if (!options.keepValue) {
|
1860
|
+
unset(_fields, fieldName);
|
1861
|
+
unset(_formValues, fieldName);
|
1757
1862
|
}
|
1758
|
-
|
1863
|
+
!options.keepError && unset(_formState.errors, fieldName);
|
1864
|
+
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
1865
|
+
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
1866
|
+
!options.keepIsValidating &&
|
1867
|
+
unset(_formState.validatingFields, fieldName);
|
1868
|
+
!_options.shouldUnregister &&
|
1869
|
+
!options.keepDefaultValue &&
|
1870
|
+
unset(_defaultValues, fieldName);
|
1759
1871
|
}
|
1760
|
-
|
1872
|
+
_subjects.state.next({
|
1873
|
+
values: { ..._formValues },
|
1874
|
+
});
|
1875
|
+
_subjects.state.next({
|
1876
|
+
..._formState,
|
1877
|
+
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
1878
|
+
});
|
1879
|
+
!options.keepIsValid && _setValid();
|
1761
1880
|
};
|
1762
|
-
const
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
delayErrorCallback = debounce(() => updateErrors(name, error));
|
1769
|
-
delayErrorCallback(_options.delayError);
|
1770
|
-
}
|
1771
|
-
else {
|
1772
|
-
clearTimeout(timer);
|
1773
|
-
delayErrorCallback = null;
|
1774
|
-
error
|
1775
|
-
? set(_formState.errors, name, error)
|
1776
|
-
: unset(_formState.errors, name);
|
1777
|
-
}
|
1778
|
-
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
1779
|
-
!isEmptyObject(fieldState) ||
|
1780
|
-
shouldUpdateValid) {
|
1781
|
-
const updatedFormState = {
|
1782
|
-
...fieldState,
|
1783
|
-
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
1784
|
-
errors: _formState.errors,
|
1785
|
-
name,
|
1786
|
-
};
|
1787
|
-
_formState = {
|
1788
|
-
..._formState,
|
1789
|
-
...updatedFormState,
|
1790
|
-
};
|
1791
|
-
_subjects.state.next(updatedFormState);
|
1881
|
+
const _setDisabledField = ({ disabled, name, field, fields, }) => {
|
1882
|
+
if ((isBoolean(disabled) && _state.mount) ||
|
1883
|
+
!!disabled ||
|
1884
|
+
_names.disabled.has(name)) {
|
1885
|
+
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
1886
|
+
updateTouchAndDirty(name, getFieldValue(field ? field._f : get(fields, name)._f), false, false, true);
|
1792
1887
|
}
|
1793
1888
|
};
|
1794
|
-
const
|
1795
|
-
|
1796
|
-
const
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1889
|
+
const register = (name, options = {}) => {
|
1890
|
+
let field = get(_fields, name);
|
1891
|
+
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
1892
|
+
set(_fields, name, {
|
1893
|
+
...(field || {}),
|
1894
|
+
_f: {
|
1895
|
+
...(field && field._f ? field._f : { ref: { name } }),
|
1896
|
+
name,
|
1897
|
+
mount: true,
|
1898
|
+
...options,
|
1899
|
+
},
|
1900
|
+
});
|
1901
|
+
_names.mount.add(name);
|
1902
|
+
if (field) {
|
1903
|
+
_setDisabledField({
|
1904
|
+
field,
|
1905
|
+
disabled: isBoolean(options.disabled)
|
1906
|
+
? options.disabled
|
1907
|
+
: _options.disabled,
|
1908
|
+
name,
|
1909
|
+
});
|
1809
1910
|
}
|
1810
1911
|
else {
|
1811
|
-
|
1912
|
+
updateValidAndValue(name, true, options.value);
|
1812
1913
|
}
|
1813
|
-
return
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1914
|
+
return {
|
1915
|
+
...(disabledIsDefined
|
1916
|
+
? { disabled: options.disabled || _options.disabled }
|
1917
|
+
: {}),
|
1918
|
+
...(_options.progressive
|
1919
|
+
? {
|
1920
|
+
required: !!options.required,
|
1921
|
+
min: getRuleValue(options.min),
|
1922
|
+
max: getRuleValue(options.max),
|
1923
|
+
minLength: getRuleValue(options.minLength),
|
1924
|
+
maxLength: getRuleValue(options.maxLength),
|
1925
|
+
pattern: getRuleValue(options.pattern),
|
1926
|
+
}
|
1927
|
+
: {}),
|
1928
|
+
name,
|
1929
|
+
onChange,
|
1930
|
+
onBlur: onChange,
|
1931
|
+
ref: (ref) => {
|
1932
|
+
if (ref) {
|
1933
|
+
register(name, options);
|
1934
|
+
field = get(_fields, name);
|
1935
|
+
const fieldRef = isUndefined(ref.value)
|
1936
|
+
? ref.querySelectorAll
|
1937
|
+
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
1938
|
+
: ref
|
1939
|
+
: ref;
|
1940
|
+
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
1941
|
+
const refs = field._f.refs || [];
|
1942
|
+
if (radioOrCheckbox
|
1943
|
+
? refs.find((option) => option === fieldRef)
|
1944
|
+
: fieldRef === field._f.ref) {
|
1945
|
+
return;
|
1831
1946
|
}
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1947
|
+
set(_fields, name, {
|
1948
|
+
_f: {
|
1949
|
+
...field._f,
|
1950
|
+
...(radioOrCheckbox
|
1951
|
+
? {
|
1952
|
+
refs: [
|
1953
|
+
...refs.filter(live),
|
1954
|
+
fieldRef,
|
1955
|
+
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
1956
|
+
],
|
1957
|
+
ref: { type: fieldRef.type, name },
|
1958
|
+
}
|
1959
|
+
: { ref: fieldRef }),
|
1960
|
+
},
|
1961
|
+
});
|
1962
|
+
updateValidAndValue(name, false, undefined, fieldRef);
|
1963
|
+
}
|
1964
|
+
else {
|
1965
|
+
field = get(_fields, name, {});
|
1966
|
+
if (field._f) {
|
1967
|
+
field._f.mount = false;
|
1837
1968
|
}
|
1838
|
-
|
1839
|
-
(
|
1840
|
-
|
1841
|
-
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
1842
|
-
: set(_formState.errors, _f.name, fieldError[_f.name])
|
1843
|
-
: unset(_formState.errors, _f.name));
|
1969
|
+
(_options.shouldUnregister || options.shouldUnregister) &&
|
1970
|
+
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
1971
|
+
_names.unMount.add(name);
|
1844
1972
|
}
|
1845
|
-
|
1846
|
-
|
1847
|
-
}
|
1848
|
-
}
|
1849
|
-
return context.valid;
|
1973
|
+
},
|
1974
|
+
};
|
1850
1975
|
};
|
1851
|
-
const
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
1856
|
-
|
1857
|
-
|
1858
|
-
|
1859
|
-
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
(name && data && set(_formValues, name, data),
|
1864
|
-
!deepEqual(getValues(), _defaultValues));
|
1865
|
-
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
1866
|
-
...(_state.mount
|
1867
|
-
? _formValues
|
1868
|
-
: isUndefined(defaultValue)
|
1869
|
-
? _defaultValues
|
1870
|
-
: isString(names)
|
1871
|
-
? { [names]: defaultValue }
|
1872
|
-
: defaultValue),
|
1873
|
-
}, isGlobal, defaultValue);
|
1874
|
-
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
1875
|
-
const setFieldValue = (name, value, options = {}) => {
|
1876
|
-
const field = get(_fields, name);
|
1877
|
-
let fieldValue = value;
|
1878
|
-
if (field) {
|
1879
|
-
const fieldReference = field._f;
|
1880
|
-
if (fieldReference) {
|
1881
|
-
!fieldReference.disabled &&
|
1882
|
-
set(_formValues, name, getFieldValueAs(value, fieldReference));
|
1883
|
-
fieldValue =
|
1884
|
-
isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
|
1885
|
-
? ''
|
1886
|
-
: value;
|
1887
|
-
if (isMultipleSelect(fieldReference.ref)) {
|
1888
|
-
[...fieldReference.ref.options].forEach((optionRef) => (optionRef.selected = fieldValue.includes(optionRef.value)));
|
1889
|
-
}
|
1890
|
-
else if (fieldReference.refs) {
|
1891
|
-
if (isCheckBoxInput(fieldReference.ref)) {
|
1892
|
-
fieldReference.refs.length > 1
|
1893
|
-
? fieldReference.refs.forEach((checkboxRef) => (!checkboxRef.defaultChecked || !checkboxRef.disabled) &&
|
1894
|
-
(checkboxRef.checked = Array.isArray(fieldValue)
|
1895
|
-
? !!fieldValue.find((data) => data === checkboxRef.value)
|
1896
|
-
: fieldValue === checkboxRef.value))
|
1897
|
-
: fieldReference.refs[0] &&
|
1898
|
-
(fieldReference.refs[0].checked = !!fieldValue);
|
1899
|
-
}
|
1900
|
-
else {
|
1901
|
-
fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
|
1902
|
-
}
|
1903
|
-
}
|
1904
|
-
else if (isFileInput(fieldReference.ref)) {
|
1905
|
-
fieldReference.ref.value = '';
|
1906
|
-
}
|
1907
|
-
else {
|
1908
|
-
fieldReference.ref.value = fieldValue;
|
1909
|
-
if (!fieldReference.ref.type) {
|
1910
|
-
_subjects.values.next({
|
1911
|
-
name,
|
1912
|
-
values: { ..._formValues },
|
1976
|
+
const _focusError = () => _options.shouldFocusError &&
|
1977
|
+
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
1978
|
+
const _disableForm = (disabled) => {
|
1979
|
+
if (isBoolean(disabled)) {
|
1980
|
+
_subjects.state.next({ disabled });
|
1981
|
+
iterateFieldsByAction(_fields, (ref, name) => {
|
1982
|
+
const currentField = get(_fields, name);
|
1983
|
+
if (currentField) {
|
1984
|
+
ref.disabled = currentField._f.disabled || disabled;
|
1985
|
+
if (Array.isArray(currentField._f.refs)) {
|
1986
|
+
currentField._f.refs.forEach((inputRef) => {
|
1987
|
+
inputRef.disabled = currentField._f.disabled || disabled;
|
1913
1988
|
});
|
1914
1989
|
}
|
1915
1990
|
}
|
1916
|
-
}
|
1991
|
+
}, 0, false);
|
1917
1992
|
}
|
1918
|
-
(options.shouldDirty || options.shouldTouch) &&
|
1919
|
-
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
|
1920
|
-
options.shouldValidate && trigger(name);
|
1921
1993
|
};
|
1922
|
-
const
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
(_names.array.has(name) ||
|
1928
|
-
isObject(fieldValue) ||
|
1929
|
-
(field && !field._f)) &&
|
1930
|
-
!isDateObject(fieldValue)
|
1931
|
-
? setValues(fieldName, fieldValue, options)
|
1932
|
-
: setFieldValue(fieldName, fieldValue, options);
|
1994
|
+
const handleSubmit = (onValid, onInvalid) => async (e) => {
|
1995
|
+
let onValidError = undefined;
|
1996
|
+
if (e) {
|
1997
|
+
e.preventDefault && e.preventDefault();
|
1998
|
+
e.persist && e.persist();
|
1933
1999
|
}
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
|
1938
|
-
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
2000
|
+
let fieldValues = cloneObject(_formValues);
|
2001
|
+
if (_names.disabled.size) {
|
2002
|
+
for (const name of _names.disabled) {
|
2003
|
+
set(fieldValues, name, undefined);
|
2004
|
+
}
|
2005
|
+
}
|
2006
|
+
_subjects.state.next({
|
2007
|
+
isSubmitting: true,
|
2008
|
+
});
|
2009
|
+
if (_options.resolver) {
|
2010
|
+
const { errors, values } = await _runSchema();
|
2011
|
+
_formState.errors = errors;
|
2012
|
+
fieldValues = values;
|
2013
|
+
}
|
2014
|
+
else {
|
2015
|
+
await executeBuiltInValidation(_fields);
|
2016
|
+
}
|
2017
|
+
unset(_formState.errors, 'root');
|
2018
|
+
if (isEmptyObject(_formState.errors)) {
|
2019
|
+
_subjects.state.next({
|
2020
|
+
errors: {},
|
1944
2021
|
});
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
isDirty: _getDirty(name, cloneValue),
|
1951
|
-
});
|
2022
|
+
try {
|
2023
|
+
await onValid(fieldValues, e);
|
2024
|
+
}
|
2025
|
+
catch (error) {
|
2026
|
+
onValidError = error;
|
1952
2027
|
}
|
1953
2028
|
}
|
1954
2029
|
else {
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
2030
|
+
if (onInvalid) {
|
2031
|
+
await onInvalid({ ..._formState.errors }, e);
|
2032
|
+
}
|
2033
|
+
_focusError();
|
2034
|
+
setTimeout(_focusError);
|
1958
2035
|
}
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
2036
|
+
_subjects.state.next({
|
2037
|
+
isSubmitted: true,
|
2038
|
+
isSubmitting: false,
|
2039
|
+
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
2040
|
+
submitCount: _formState.submitCount + 1,
|
2041
|
+
errors: _formState.errors,
|
1963
2042
|
});
|
2043
|
+
if (onValidError) {
|
2044
|
+
throw onValidError;
|
2045
|
+
}
|
1964
2046
|
};
|
1965
|
-
const
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
1969
|
-
let isFieldValueUpdated = true;
|
1970
|
-
const field = get(_fields, name);
|
1971
|
-
const getCurrentFieldValue = () => target.type ? getFieldValue(field._f) : getEventValue(event);
|
1972
|
-
const _updateIsFieldValueUpdated = (fieldValue) => {
|
1973
|
-
isFieldValueUpdated =
|
1974
|
-
Number.isNaN(fieldValue) ||
|
1975
|
-
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
1976
|
-
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
1977
|
-
};
|
1978
|
-
if (field) {
|
1979
|
-
let error;
|
1980
|
-
let isValid;
|
1981
|
-
const fieldValue = getCurrentFieldValue();
|
1982
|
-
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
1983
|
-
const shouldSkipValidation = (!hasValidation(field._f) &&
|
1984
|
-
!_options.resolver &&
|
1985
|
-
!get(_formState.errors, name) &&
|
1986
|
-
!field._f.deps) ||
|
1987
|
-
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
|
1988
|
-
const watched = isWatched(name, _names, isBlurEvent);
|
1989
|
-
set(_formValues, name, fieldValue);
|
1990
|
-
if (isBlurEvent) {
|
1991
|
-
field._f.onBlur && field._f.onBlur(event);
|
1992
|
-
delayErrorCallback && delayErrorCallback(0);
|
1993
|
-
}
|
1994
|
-
else if (field._f.onChange) {
|
1995
|
-
field._f.onChange(event);
|
2047
|
+
const resetField = (name, options = {}) => {
|
2048
|
+
if (get(_fields, name)) {
|
2049
|
+
if (isUndefined(options.defaultValue)) {
|
2050
|
+
setValue(name, cloneObject(get(_defaultValues, name)));
|
1996
2051
|
}
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
_subjects.values.next({
|
2001
|
-
name,
|
2002
|
-
type: event.type,
|
2003
|
-
values: { ..._formValues },
|
2004
|
-
});
|
2005
|
-
if (shouldSkipValidation) {
|
2006
|
-
if (_proxyFormState.isValid) {
|
2007
|
-
if (_options.mode === 'onBlur') {
|
2008
|
-
if (isBlurEvent) {
|
2009
|
-
_updateValid();
|
2010
|
-
}
|
2011
|
-
}
|
2012
|
-
else {
|
2013
|
-
_updateValid();
|
2014
|
-
}
|
2015
|
-
}
|
2016
|
-
return (shouldRender &&
|
2017
|
-
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
|
2052
|
+
else {
|
2053
|
+
setValue(name, options.defaultValue);
|
2054
|
+
set(_defaultValues, name, cloneObject(options.defaultValue));
|
2018
2055
|
}
|
2019
|
-
!
|
2020
|
-
|
2021
|
-
const { errors } = await _executeSchema([name]);
|
2022
|
-
_updateIsFieldValueUpdated(fieldValue);
|
2023
|
-
if (isFieldValueUpdated) {
|
2024
|
-
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
2025
|
-
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
2026
|
-
error = errorLookupResult.error;
|
2027
|
-
name = errorLookupResult.name;
|
2028
|
-
isValid = isEmptyObject(errors);
|
2029
|
-
}
|
2056
|
+
if (!options.keepTouched) {
|
2057
|
+
unset(_formState.touchedFields, name);
|
2030
2058
|
}
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
|
2035
|
-
|
2036
|
-
if (isFieldValueUpdated) {
|
2037
|
-
if (error) {
|
2038
|
-
isValid = false;
|
2039
|
-
}
|
2040
|
-
else if (_proxyFormState.isValid) {
|
2041
|
-
isValid = await executeBuiltInValidation(_fields, true);
|
2042
|
-
}
|
2043
|
-
}
|
2059
|
+
if (!options.keepDirty) {
|
2060
|
+
unset(_formState.dirtyFields, name);
|
2061
|
+
_formState.isDirty = options.defaultValue
|
2062
|
+
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
2063
|
+
: _getDirty();
|
2044
2064
|
}
|
2045
|
-
if (
|
2046
|
-
|
2047
|
-
|
2048
|
-
shouldRenderByError(name, isValid, error, fieldState);
|
2065
|
+
if (!options.keepError) {
|
2066
|
+
unset(_formState.errors, name);
|
2067
|
+
_proxyFormState.isValid && _setValid();
|
2049
2068
|
}
|
2069
|
+
_subjects.state.next({ ..._formState });
|
2050
2070
|
}
|
2051
2071
|
};
|
2052
|
-
const
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2072
|
+
const _reset = (formValues, keepStateOptions = {}) => {
|
2073
|
+
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
|
2074
|
+
const cloneUpdatedValues = cloneObject(updatedValues);
|
2075
|
+
const isEmptyResetValues = isEmptyObject(formValues);
|
2076
|
+
const values = isEmptyResetValues ? _defaultValues : cloneUpdatedValues;
|
2077
|
+
if (!keepStateOptions.keepDefaultValues) {
|
2078
|
+
_defaultValues = updatedValues;
|
2056
2079
|
}
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2080
|
+
if (!keepStateOptions.keepValues) {
|
2081
|
+
if (keepStateOptions.keepDirtyValues) {
|
2082
|
+
const fieldsToCheck = new Set([
|
2083
|
+
..._names.mount,
|
2084
|
+
...Object.keys(getDirtyFields(_defaultValues, _formValues)),
|
2085
|
+
]);
|
2086
|
+
for (const fieldName of Array.from(fieldsToCheck)) {
|
2087
|
+
get(_formState.dirtyFields, fieldName)
|
2088
|
+
? set(values, fieldName, get(_formValues, fieldName))
|
2089
|
+
: setValue(fieldName, get(values, fieldName));
|
2090
|
+
}
|
2091
|
+
}
|
2092
|
+
else {
|
2093
|
+
if (isWeb && isUndefined(formValues)) {
|
2094
|
+
for (const name of _names.mount) {
|
2095
|
+
const field = get(_fields, name);
|
2096
|
+
if (field && field._f) {
|
2097
|
+
const fieldReference = Array.isArray(field._f.refs)
|
2098
|
+
? field._f.refs[0]
|
2099
|
+
: field._f.ref;
|
2100
|
+
if (isHTMLElement(fieldReference)) {
|
2101
|
+
const form = fieldReference.closest('form');
|
2102
|
+
if (form) {
|
2103
|
+
form.reset();
|
2104
|
+
break;
|
2105
|
+
}
|
2106
|
+
}
|
2107
|
+
}
|
2108
|
+
}
|
2109
|
+
}
|
2110
|
+
_fields = {};
|
2111
|
+
}
|
2112
|
+
_formValues = _options.shouldUnregister
|
2113
|
+
? keepStateOptions.keepDefaultValues
|
2114
|
+
? cloneObject(_defaultValues)
|
2115
|
+
: {}
|
2116
|
+
: cloneObject(values);
|
2117
|
+
_subjects.array.next({
|
2118
|
+
values: { ...values },
|
2119
|
+
});
|
2120
|
+
_subjects.state.next({
|
2121
|
+
values: { ...values },
|
2122
|
+
});
|
2079
2123
|
}
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
options.shouldFocus &&
|
2089
|
-
!validationResult &&
|
2090
|
-
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
2091
|
-
return validationResult;
|
2092
|
-
};
|
2093
|
-
const getValues = (fieldNames) => {
|
2094
|
-
const values = {
|
2095
|
-
...(_state.mount ? _formValues : _defaultValues),
|
2124
|
+
_names = {
|
2125
|
+
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
|
2126
|
+
unMount: new Set(),
|
2127
|
+
array: new Set(),
|
2128
|
+
disabled: new Set(),
|
2129
|
+
watch: new Set(),
|
2130
|
+
watchAll: false,
|
2131
|
+
focus: '',
|
2096
2132
|
};
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2102
|
-
};
|
2103
|
-
const getFieldState = (name, formState) => ({
|
2104
|
-
invalid: !!get((formState || _formState).errors, name),
|
2105
|
-
isDirty: !!get((formState || _formState).dirtyFields, name),
|
2106
|
-
error: get((formState || _formState).errors, name),
|
2107
|
-
isValidating: !!get(_formState.validatingFields, name),
|
2108
|
-
isTouched: !!get((formState || _formState).touchedFields, name),
|
2109
|
-
});
|
2110
|
-
const clearErrors = (name) => {
|
2111
|
-
name &&
|
2112
|
-
convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
|
2113
|
-
_subjects.state.next({
|
2114
|
-
errors: name ? _formState.errors : {},
|
2115
|
-
});
|
2116
|
-
};
|
2117
|
-
const setError = (name, error, options) => {
|
2118
|
-
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
2119
|
-
const currentError = get(_formState.errors, name) || {};
|
2120
|
-
// Don't override existing error messages elsewhere in the object tree.
|
2121
|
-
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
2122
|
-
set(_formState.errors, name, {
|
2123
|
-
...restOfErrorTree,
|
2124
|
-
...error,
|
2125
|
-
ref,
|
2126
|
-
});
|
2133
|
+
_state.mount =
|
2134
|
+
!_proxyFormState.isValid ||
|
2135
|
+
!!keepStateOptions.keepIsValid ||
|
2136
|
+
!!keepStateOptions.keepDirtyValues;
|
2137
|
+
_state.watch = !!_options.shouldUnregister;
|
2127
2138
|
_subjects.state.next({
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2139
|
+
submitCount: keepStateOptions.keepSubmitCount
|
2140
|
+
? _formState.submitCount
|
2141
|
+
: 0,
|
2142
|
+
isDirty: isEmptyResetValues
|
2143
|
+
? false
|
2144
|
+
: keepStateOptions.keepDirty
|
2145
|
+
? _formState.isDirty
|
2146
|
+
: !!(keepStateOptions.keepDefaultValues &&
|
2147
|
+
!deepEqual(formValues, _defaultValues)),
|
2148
|
+
isSubmitted: keepStateOptions.keepIsSubmitted
|
2149
|
+
? _formState.isSubmitted
|
2150
|
+
: false,
|
2151
|
+
dirtyFields: isEmptyResetValues
|
2152
|
+
? {}
|
2153
|
+
: keepStateOptions.keepDirtyValues
|
2154
|
+
? keepStateOptions.keepDefaultValues && _formValues
|
2155
|
+
? getDirtyFields(_defaultValues, _formValues)
|
2156
|
+
: _formState.dirtyFields
|
2157
|
+
: keepStateOptions.keepDefaultValues && formValues
|
2158
|
+
? getDirtyFields(_defaultValues, formValues)
|
2159
|
+
: keepStateOptions.keepDirty
|
2160
|
+
? _formState.dirtyFields
|
2161
|
+
: {},
|
2162
|
+
touchedFields: keepStateOptions.keepTouched
|
2163
|
+
? _formState.touchedFields
|
2164
|
+
: {},
|
2165
|
+
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
2166
|
+
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
2167
|
+
? _formState.isSubmitSuccessful
|
2168
|
+
: false,
|
2169
|
+
isSubmitting: false,
|
2131
2170
|
});
|
2132
|
-
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
2133
2171
|
};
|
2134
|
-
const
|
2135
|
-
?
|
2136
|
-
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2172
|
+
const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
|
2173
|
+
? formValues(_formValues)
|
2174
|
+
: formValues, keepStateOptions);
|
2175
|
+
const setFocus = (name, options = {}) => {
|
2176
|
+
const field = get(_fields, name);
|
2177
|
+
const fieldReference = field && field._f;
|
2178
|
+
if (fieldReference) {
|
2179
|
+
const fieldRef = fieldReference.refs
|
2180
|
+
? fieldReference.refs[0]
|
2181
|
+
: fieldReference.ref;
|
2182
|
+
if (fieldRef.focus) {
|
2183
|
+
fieldRef.focus();
|
2184
|
+
options.shouldSelect &&
|
2185
|
+
isFunction(fieldRef.select) &&
|
2186
|
+
fieldRef.select();
|
2146
2187
|
}
|
2147
|
-
!options.keepError && unset(_formState.errors, fieldName);
|
2148
|
-
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
2149
|
-
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
2150
|
-
!options.keepIsValidating &&
|
2151
|
-
unset(_formState.validatingFields, fieldName);
|
2152
|
-
!_options.shouldUnregister &&
|
2153
|
-
!options.keepDefaultValue &&
|
2154
|
-
unset(_defaultValues, fieldName);
|
2155
2188
|
}
|
2156
|
-
_subjects.values.next({
|
2157
|
-
values: { ..._formValues },
|
2158
|
-
});
|
2159
|
-
_subjects.state.next({
|
2160
|
-
..._formState,
|
2161
|
-
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
2162
|
-
});
|
2163
|
-
!options.keepIsValid && _updateValid();
|
2164
2189
|
};
|
2165
|
-
const
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
? getFieldValue(field ? field._f : get(fields, name)._f)
|
2171
|
-
: value;
|
2172
|
-
if (disabled || (!disabled && !isUndefined(inputValue))) {
|
2173
|
-
set(_formValues, name, inputValue);
|
2174
|
-
}
|
2175
|
-
updateTouchAndDirty(name, inputValue, false, false, true);
|
2176
|
-
}
|
2190
|
+
const _setFormState = (updatedFormState) => {
|
2191
|
+
_formState = {
|
2192
|
+
..._formState,
|
2193
|
+
...updatedFormState,
|
2194
|
+
};
|
2177
2195
|
};
|
2178
|
-
const
|
2179
|
-
|
2180
|
-
|
2181
|
-
|
2182
|
-
|
2183
|
-
_f: {
|
2184
|
-
...(field && field._f ? field._f : { ref: { name } }),
|
2185
|
-
name,
|
2186
|
-
mount: true,
|
2187
|
-
...options,
|
2188
|
-
},
|
2189
|
-
});
|
2190
|
-
_names.mount.add(name);
|
2191
|
-
if (field) {
|
2192
|
-
_updateDisabledField({
|
2193
|
-
field,
|
2194
|
-
disabled: isBoolean(options.disabled)
|
2195
|
-
? options.disabled
|
2196
|
-
: _options.disabled,
|
2197
|
-
name,
|
2198
|
-
value: options.value,
|
2196
|
+
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
2197
|
+
_options.defaultValues().then((values) => {
|
2198
|
+
reset(values, _options.resetOptions);
|
2199
|
+
_subjects.state.next({
|
2200
|
+
isLoading: false,
|
2199
2201
|
});
|
2200
|
-
}
|
2201
|
-
|
2202
|
-
|
2203
|
-
|
2204
|
-
|
2205
|
-
|
2206
|
-
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
2224
|
-
|
2225
|
-
const fieldRef = isUndefined(ref.value)
|
2226
|
-
? ref.querySelectorAll
|
2227
|
-
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
2228
|
-
: ref
|
2229
|
-
: ref;
|
2230
|
-
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
2231
|
-
const refs = field._f.refs || [];
|
2232
|
-
if (radioOrCheckbox
|
2233
|
-
? refs.find((option) => option === fieldRef)
|
2234
|
-
: fieldRef === field._f.ref) {
|
2235
|
-
return;
|
2236
|
-
}
|
2237
|
-
set(_fields, name, {
|
2238
|
-
_f: {
|
2239
|
-
...field._f,
|
2240
|
-
...(radioOrCheckbox
|
2241
|
-
? {
|
2242
|
-
refs: [
|
2243
|
-
...refs.filter(live),
|
2244
|
-
fieldRef,
|
2245
|
-
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
2246
|
-
],
|
2247
|
-
ref: { type: fieldRef.type, name },
|
2248
|
-
}
|
2249
|
-
: { ref: fieldRef }),
|
2250
|
-
},
|
2251
|
-
});
|
2252
|
-
updateValidAndValue(name, false, undefined, fieldRef);
|
2253
|
-
}
|
2254
|
-
else {
|
2255
|
-
field = get(_fields, name, {});
|
2256
|
-
if (field._f) {
|
2257
|
-
field._f.mount = false;
|
2258
|
-
}
|
2259
|
-
(_options.shouldUnregister || options.shouldUnregister) &&
|
2260
|
-
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
2261
|
-
_names.unMount.add(name);
|
2262
|
-
}
|
2202
|
+
});
|
2203
|
+
const methods = {
|
2204
|
+
control: {
|
2205
|
+
register,
|
2206
|
+
unregister,
|
2207
|
+
getFieldState,
|
2208
|
+
handleSubmit,
|
2209
|
+
setError,
|
2210
|
+
_subscribe,
|
2211
|
+
_runSchema,
|
2212
|
+
_getWatch,
|
2213
|
+
_getDirty,
|
2214
|
+
_setValid,
|
2215
|
+
_setFieldArray,
|
2216
|
+
_setDisabledField,
|
2217
|
+
_setErrors,
|
2218
|
+
_getFieldArray,
|
2219
|
+
_reset,
|
2220
|
+
_resetDefaultValues,
|
2221
|
+
_removeUnmounted,
|
2222
|
+
_disableForm,
|
2223
|
+
_subjects,
|
2224
|
+
_proxyFormState,
|
2225
|
+
get _fields() {
|
2226
|
+
return _fields;
|
2263
2227
|
},
|
2264
|
-
|
2228
|
+
get _formValues() {
|
2229
|
+
return _formValues;
|
2230
|
+
},
|
2231
|
+
get _state() {
|
2232
|
+
return _state;
|
2233
|
+
},
|
2234
|
+
set _state(value) {
|
2235
|
+
_state = value;
|
2236
|
+
},
|
2237
|
+
get _defaultValues() {
|
2238
|
+
return _defaultValues;
|
2239
|
+
},
|
2240
|
+
get _names() {
|
2241
|
+
return _names;
|
2242
|
+
},
|
2243
|
+
set _names(value) {
|
2244
|
+
_names = value;
|
2245
|
+
},
|
2246
|
+
get _formState() {
|
2247
|
+
return _formState;
|
2248
|
+
},
|
2249
|
+
get _options() {
|
2250
|
+
return _options;
|
2251
|
+
},
|
2252
|
+
set _options(value) {
|
2253
|
+
_options = {
|
2254
|
+
..._options,
|
2255
|
+
...value,
|
2256
|
+
};
|
2257
|
+
},
|
2258
|
+
},
|
2259
|
+
subscribe,
|
2260
|
+
trigger,
|
2261
|
+
register,
|
2262
|
+
handleSubmit,
|
2263
|
+
watch,
|
2264
|
+
setValue,
|
2265
|
+
getValues,
|
2266
|
+
reset,
|
2267
|
+
resetField,
|
2268
|
+
clearErrors,
|
2269
|
+
unregister,
|
2270
|
+
setError,
|
2271
|
+
setFocus,
|
2272
|
+
getFieldState,
|
2265
2273
|
};
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
if (isBoolean(disabled)) {
|
2270
|
-
_subjects.state.next({ disabled });
|
2271
|
-
iterateFieldsByAction(_fields, (ref, name) => {
|
2272
|
-
const currentField = get(_fields, name);
|
2273
|
-
if (currentField) {
|
2274
|
-
ref.disabled = currentField._f.disabled || disabled;
|
2275
|
-
if (Array.isArray(currentField._f.refs)) {
|
2276
|
-
currentField._f.refs.forEach((inputRef) => {
|
2277
|
-
inputRef.disabled = currentField._f.disabled || disabled;
|
2278
|
-
});
|
2279
|
-
}
|
2280
|
-
}
|
2281
|
-
}, 0, false);
|
2282
|
-
}
|
2274
|
+
return {
|
2275
|
+
...methods,
|
2276
|
+
formControl: methods,
|
2283
2277
|
};
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2278
|
+
}
|
2279
|
+
|
2280
|
+
var generateId = () => {
|
2281
|
+
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
|
2282
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
2283
|
+
const r = (Math.random() * 16 + d) % 16 | 0;
|
2284
|
+
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
2285
|
+
});
|
2286
|
+
};
|
2287
|
+
|
2288
|
+
var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
|
2289
|
+
? options.focusName ||
|
2290
|
+
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
2291
|
+
: '';
|
2292
|
+
|
2293
|
+
var appendAt = (data, value) => [
|
2294
|
+
...data,
|
2295
|
+
...convertToArrayPayload(value),
|
2296
|
+
];
|
2297
|
+
|
2298
|
+
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
|
2299
|
+
|
2300
|
+
function insert(data, index, value) {
|
2301
|
+
return [
|
2302
|
+
...data.slice(0, index),
|
2303
|
+
...convertToArrayPayload(value),
|
2304
|
+
...data.slice(index),
|
2305
|
+
];
|
2306
|
+
}
|
2307
|
+
|
2308
|
+
var moveArrayAt = (data, from, to) => {
|
2309
|
+
if (!Array.isArray(data)) {
|
2310
|
+
return [];
|
2311
|
+
}
|
2312
|
+
if (isUndefined(data[to])) {
|
2313
|
+
data[to] = undefined;
|
2314
|
+
}
|
2315
|
+
data.splice(to, 0, data.splice(from, 1)[0]);
|
2316
|
+
return data;
|
2317
|
+
};
|
2318
|
+
|
2319
|
+
var prependAt = (data, value) => [
|
2320
|
+
...convertToArrayPayload(value),
|
2321
|
+
...convertToArrayPayload(data),
|
2322
|
+
];
|
2323
|
+
|
2324
|
+
function removeAtIndexes(data, indexes) {
|
2325
|
+
let i = 0;
|
2326
|
+
const temp = [...data];
|
2327
|
+
for (const index of indexes) {
|
2328
|
+
temp.splice(index - i, 1);
|
2329
|
+
i++;
|
2330
|
+
}
|
2331
|
+
return compact(temp).length ? temp : [];
|
2332
|
+
}
|
2333
|
+
var removeArrayAt = (data, index) => isUndefined(index)
|
2334
|
+
? []
|
2335
|
+
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
2336
|
+
|
2337
|
+
var swapArrayAt = (data, indexA, indexB) => {
|
2338
|
+
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
2339
|
+
};
|
2340
|
+
|
2341
|
+
var updateAt = (fieldValues, index, value) => {
|
2342
|
+
fieldValues[index] = value;
|
2343
|
+
return fieldValues;
|
2344
|
+
};
|
2345
|
+
|
2346
|
+
/**
|
2347
|
+
* A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A)
|
2348
|
+
*
|
2349
|
+
* @remarks
|
2350
|
+
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
2351
|
+
*
|
2352
|
+
* @param props - useFieldArray props
|
2353
|
+
*
|
2354
|
+
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
2355
|
+
*
|
2356
|
+
* @example
|
2357
|
+
* ```tsx
|
2358
|
+
* function App() {
|
2359
|
+
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
2360
|
+
* defaultValues: {
|
2361
|
+
* test: []
|
2362
|
+
* }
|
2363
|
+
* });
|
2364
|
+
* const { fields, append } = useFieldArray({
|
2365
|
+
* control,
|
2366
|
+
* name: "test"
|
2367
|
+
* });
|
2368
|
+
*
|
2369
|
+
* return (
|
2370
|
+
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
2371
|
+
* {fields.map((item, index) => (
|
2372
|
+
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
2373
|
+
* ))}
|
2374
|
+
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
2375
|
+
* append
|
2376
|
+
* </button>
|
2377
|
+
* <input type="submit" />
|
2378
|
+
* </form>
|
2379
|
+
* );
|
2380
|
+
* }
|
2381
|
+
* ```
|
2382
|
+
*/
|
2383
|
+
function useFieldArray(props) {
|
2384
|
+
const methods = useFormContext();
|
2385
|
+
const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
|
2386
|
+
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
2387
|
+
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
2388
|
+
const _fieldIds = React.useRef(fields);
|
2389
|
+
const _name = React.useRef(name);
|
2390
|
+
const _actioned = React.useRef(false);
|
2391
|
+
_name.current = name;
|
2392
|
+
_fieldIds.current = fields;
|
2393
|
+
control._names.array.add(name);
|
2394
|
+
rules &&
|
2395
|
+
control.register(name, rules);
|
2396
|
+
React.useEffect(() => control._subjects.array.subscribe({
|
2397
|
+
next: ({ values, name: fieldArrayName, }) => {
|
2398
|
+
if (fieldArrayName === _name.current || !fieldArrayName) {
|
2399
|
+
const fieldValues = get(values, _name.current);
|
2400
|
+
if (Array.isArray(fieldValues)) {
|
2401
|
+
setFields(fieldValues);
|
2402
|
+
ids.current = fieldValues.map(generateId);
|
2403
|
+
}
|
2293
2404
|
}
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
|
2405
|
+
},
|
2406
|
+
}).unsubscribe, [control]);
|
2407
|
+
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
2408
|
+
_actioned.current = true;
|
2409
|
+
control._setFieldArray(name, updatedFieldArrayValues);
|
2410
|
+
}, [control, name]);
|
2411
|
+
const append = (value, options) => {
|
2412
|
+
const appendValue = convertToArrayPayload(cloneObject(value));
|
2413
|
+
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
|
2414
|
+
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
|
2415
|
+
ids.current = appendAt(ids.current, appendValue.map(generateId));
|
2416
|
+
updateValues(updatedFieldArrayValues);
|
2417
|
+
setFields(updatedFieldArrayValues);
|
2418
|
+
control._setFieldArray(name, updatedFieldArrayValues, appendAt, {
|
2419
|
+
argA: fillEmptyArray(value),
|
2299
2420
|
});
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
_subjects.state.next({
|
2311
|
-
errors: {},
|
2312
|
-
});
|
2313
|
-
try {
|
2314
|
-
await onValid(fieldValues, e);
|
2315
|
-
}
|
2316
|
-
catch (error) {
|
2317
|
-
onValidError = error;
|
2318
|
-
}
|
2319
|
-
}
|
2320
|
-
else {
|
2321
|
-
if (onInvalid) {
|
2322
|
-
await onInvalid({ ..._formState.errors }, e);
|
2323
|
-
}
|
2324
|
-
_focusError();
|
2325
|
-
setTimeout(_focusError);
|
2326
|
-
}
|
2327
|
-
_subjects.state.next({
|
2328
|
-
isSubmitted: true,
|
2329
|
-
isSubmitting: false,
|
2330
|
-
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
2331
|
-
submitCount: _formState.submitCount + 1,
|
2332
|
-
errors: _formState.errors,
|
2421
|
+
};
|
2422
|
+
const prepend = (value, options) => {
|
2423
|
+
const prependValue = convertToArrayPayload(cloneObject(value));
|
2424
|
+
const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
|
2425
|
+
control._names.focus = getFocusFieldName(name, 0, options);
|
2426
|
+
ids.current = prependAt(ids.current, prependValue.map(generateId));
|
2427
|
+
updateValues(updatedFieldArrayValues);
|
2428
|
+
setFields(updatedFieldArrayValues);
|
2429
|
+
control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
|
2430
|
+
argA: fillEmptyArray(value),
|
2333
2431
|
});
|
2334
|
-
if (onValidError) {
|
2335
|
-
throw onValidError;
|
2336
|
-
}
|
2337
2432
|
};
|
2338
|
-
const
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2433
|
+
const remove = (index) => {
|
2434
|
+
const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
|
2435
|
+
ids.current = removeArrayAt(ids.current, index);
|
2436
|
+
updateValues(updatedFieldArrayValues);
|
2437
|
+
setFields(updatedFieldArrayValues);
|
2438
|
+
!Array.isArray(get(control._fields, name)) &&
|
2439
|
+
set(control._fields, name, undefined);
|
2440
|
+
control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
|
2441
|
+
argA: index,
|
2442
|
+
});
|
2443
|
+
};
|
2444
|
+
const insert$1 = (index, value, options) => {
|
2445
|
+
const insertValue = convertToArrayPayload(cloneObject(value));
|
2446
|
+
const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
|
2447
|
+
control._names.focus = getFocusFieldName(name, index, options);
|
2448
|
+
ids.current = insert(ids.current, index, insertValue.map(generateId));
|
2449
|
+
updateValues(updatedFieldArrayValues);
|
2450
|
+
setFields(updatedFieldArrayValues);
|
2451
|
+
control._setFieldArray(name, updatedFieldArrayValues, insert, {
|
2452
|
+
argA: index,
|
2453
|
+
argB: fillEmptyArray(value),
|
2454
|
+
});
|
2455
|
+
};
|
2456
|
+
const swap = (indexA, indexB) => {
|
2457
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
2458
|
+
swapArrayAt(updatedFieldArrayValues, indexA, indexB);
|
2459
|
+
swapArrayAt(ids.current, indexA, indexB);
|
2460
|
+
updateValues(updatedFieldArrayValues);
|
2461
|
+
setFields(updatedFieldArrayValues);
|
2462
|
+
control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
|
2463
|
+
argA: indexA,
|
2464
|
+
argB: indexB,
|
2465
|
+
}, false);
|
2466
|
+
};
|
2467
|
+
const move = (from, to) => {
|
2468
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
2469
|
+
moveArrayAt(updatedFieldArrayValues, from, to);
|
2470
|
+
moveArrayAt(ids.current, from, to);
|
2471
|
+
updateValues(updatedFieldArrayValues);
|
2472
|
+
setFields(updatedFieldArrayValues);
|
2473
|
+
control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
|
2474
|
+
argA: from,
|
2475
|
+
argB: to,
|
2476
|
+
}, false);
|
2477
|
+
};
|
2478
|
+
const update = (index, value) => {
|
2479
|
+
const updateValue = cloneObject(value);
|
2480
|
+
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
|
2481
|
+
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
2482
|
+
updateValues(updatedFieldArrayValues);
|
2483
|
+
setFields([...updatedFieldArrayValues]);
|
2484
|
+
control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
|
2485
|
+
argA: index,
|
2486
|
+
argB: updateValue,
|
2487
|
+
}, true, false);
|
2488
|
+
};
|
2489
|
+
const replace = (value) => {
|
2490
|
+
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
|
2491
|
+
ids.current = updatedFieldArrayValues.map(generateId);
|
2492
|
+
updateValues([...updatedFieldArrayValues]);
|
2493
|
+
setFields([...updatedFieldArrayValues]);
|
2494
|
+
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
2362
2495
|
};
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
if (
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2496
|
+
React.useEffect(() => {
|
2497
|
+
control._state.action = false;
|
2498
|
+
isWatched(name, control._names) &&
|
2499
|
+
control._subjects.state.next({
|
2500
|
+
...control._formState,
|
2501
|
+
});
|
2502
|
+
if (_actioned.current &&
|
2503
|
+
(!getValidationModes(control._options.mode).isOnSubmit ||
|
2504
|
+
control._formState.isSubmitted)) {
|
2505
|
+
if (control._options.resolver) {
|
2506
|
+
control._runSchema([name]).then((result) => {
|
2507
|
+
const error = get(result.errors, name);
|
2508
|
+
const existingError = get(control._formState.errors, name);
|
2509
|
+
if (existingError
|
2510
|
+
? (!error && existingError.type) ||
|
2511
|
+
(error &&
|
2512
|
+
(existingError.type !== error.type ||
|
2513
|
+
existingError.message !== error.message))
|
2514
|
+
: error && error.type) {
|
2515
|
+
error
|
2516
|
+
? set(control._formState.errors, name, error)
|
2517
|
+
: unset(control._formState.errors, name);
|
2518
|
+
control._subjects.state.next({
|
2519
|
+
errors: control._formState.errors,
|
2520
|
+
});
|
2521
|
+
}
|
2522
|
+
});
|
2382
2523
|
}
|
2383
2524
|
else {
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
if (form) {
|
2394
|
-
form.reset();
|
2395
|
-
break;
|
2396
|
-
}
|
2397
|
-
}
|
2398
|
-
}
|
2399
|
-
}
|
2525
|
+
const field = get(control._fields, name);
|
2526
|
+
if (field &&
|
2527
|
+
field._f &&
|
2528
|
+
!(getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
2529
|
+
getValidationModes(control._options.mode).isOnSubmit)) {
|
2530
|
+
validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
|
2531
|
+
control._subjects.state.next({
|
2532
|
+
errors: updateFieldArrayRootError(control._formState.errors, error, name),
|
2533
|
+
}));
|
2400
2534
|
}
|
2401
|
-
_fields = {};
|
2402
2535
|
}
|
2403
|
-
_formValues = _options.shouldUnregister
|
2404
|
-
? keepStateOptions.keepDefaultValues
|
2405
|
-
? cloneObject(_defaultValues)
|
2406
|
-
: {}
|
2407
|
-
: cloneObject(values);
|
2408
|
-
_subjects.array.next({
|
2409
|
-
values: { ...values },
|
2410
|
-
});
|
2411
|
-
_subjects.values.next({
|
2412
|
-
values: { ...values },
|
2413
|
-
});
|
2414
2536
|
}
|
2415
|
-
|
2416
|
-
|
2417
|
-
|
2418
|
-
array: new Set(),
|
2419
|
-
watch: new Set(),
|
2420
|
-
watchAll: false,
|
2421
|
-
focus: '',
|
2422
|
-
};
|
2423
|
-
_state.mount =
|
2424
|
-
!_proxyFormState.isValid ||
|
2425
|
-
!!keepStateOptions.keepIsValid ||
|
2426
|
-
!!keepStateOptions.keepDirtyValues;
|
2427
|
-
_state.watch = !!_options.shouldUnregister;
|
2428
|
-
_subjects.state.next({
|
2429
|
-
submitCount: keepStateOptions.keepSubmitCount
|
2430
|
-
? _formState.submitCount
|
2431
|
-
: 0,
|
2432
|
-
isDirty: isEmptyResetValues
|
2433
|
-
? false
|
2434
|
-
: keepStateOptions.keepDirty
|
2435
|
-
? _formState.isDirty
|
2436
|
-
: !!(keepStateOptions.keepDefaultValues &&
|
2437
|
-
!deepEqual(formValues, _defaultValues)),
|
2438
|
-
isSubmitted: keepStateOptions.keepIsSubmitted
|
2439
|
-
? _formState.isSubmitted
|
2440
|
-
: false,
|
2441
|
-
dirtyFields: isEmptyResetValues
|
2442
|
-
? {}
|
2443
|
-
: keepStateOptions.keepDirtyValues
|
2444
|
-
? keepStateOptions.keepDefaultValues && _formValues
|
2445
|
-
? getDirtyFields(_defaultValues, _formValues)
|
2446
|
-
: _formState.dirtyFields
|
2447
|
-
: keepStateOptions.keepDefaultValues && formValues
|
2448
|
-
? getDirtyFields(_defaultValues, formValues)
|
2449
|
-
: keepStateOptions.keepDirty
|
2450
|
-
? _formState.dirtyFields
|
2451
|
-
: {},
|
2452
|
-
touchedFields: keepStateOptions.keepTouched
|
2453
|
-
? _formState.touchedFields
|
2454
|
-
: {},
|
2455
|
-
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
2456
|
-
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
2457
|
-
? _formState.isSubmitSuccessful
|
2458
|
-
: false,
|
2459
|
-
isSubmitting: false,
|
2537
|
+
control._subjects.state.next({
|
2538
|
+
name,
|
2539
|
+
values: { ...control._formValues },
|
2460
2540
|
});
|
2461
|
-
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
2468
|
-
|
2469
|
-
|
2470
|
-
? fieldReference.refs[0]
|
2471
|
-
: fieldReference.ref;
|
2472
|
-
if (fieldRef.focus) {
|
2473
|
-
fieldRef.focus();
|
2474
|
-
options.shouldSelect &&
|
2475
|
-
isFunction(fieldRef.select) &&
|
2476
|
-
fieldRef.select();
|
2477
|
-
}
|
2478
|
-
}
|
2479
|
-
};
|
2480
|
-
const _updateFormState = (updatedFormState) => {
|
2481
|
-
_formState = {
|
2482
|
-
..._formState,
|
2483
|
-
...updatedFormState,
|
2484
|
-
};
|
2485
|
-
};
|
2486
|
-
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
2487
|
-
_options.defaultValues().then((values) => {
|
2488
|
-
reset(values, _options.resetOptions);
|
2489
|
-
_subjects.state.next({
|
2490
|
-
isLoading: false,
|
2541
|
+
control._names.focus &&
|
2542
|
+
iterateFieldsByAction(control._fields, (ref, key) => {
|
2543
|
+
if (control._names.focus &&
|
2544
|
+
key.startsWith(control._names.focus) &&
|
2545
|
+
ref.focus) {
|
2546
|
+
ref.focus();
|
2547
|
+
return 1;
|
2548
|
+
}
|
2549
|
+
return;
|
2491
2550
|
});
|
2492
|
-
|
2551
|
+
control._names.focus = '';
|
2552
|
+
control._setValid();
|
2553
|
+
_actioned.current = false;
|
2554
|
+
}, [fields, name, control]);
|
2555
|
+
React.useEffect(() => {
|
2556
|
+
!get(control._formValues, name) && control._setFieldArray(name);
|
2557
|
+
return () => {
|
2558
|
+
(control._options.shouldUnregister || shouldUnregister) &&
|
2559
|
+
control.unregister(name);
|
2560
|
+
};
|
2561
|
+
}, [name, control, keyName, shouldUnregister]);
|
2493
2562
|
return {
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2506
|
-
_updateDisabledField,
|
2507
|
-
_getFieldArray,
|
2508
|
-
_reset,
|
2509
|
-
_resetDefaultValues,
|
2510
|
-
_updateFormState,
|
2511
|
-
_disableForm,
|
2512
|
-
_subjects,
|
2513
|
-
_proxyFormState,
|
2514
|
-
_setErrors,
|
2515
|
-
get _fields() {
|
2516
|
-
return _fields;
|
2517
|
-
},
|
2518
|
-
get _formValues() {
|
2519
|
-
return _formValues;
|
2520
|
-
},
|
2521
|
-
get _state() {
|
2522
|
-
return _state;
|
2523
|
-
},
|
2524
|
-
set _state(value) {
|
2525
|
-
_state = value;
|
2526
|
-
},
|
2527
|
-
get _defaultValues() {
|
2528
|
-
return _defaultValues;
|
2529
|
-
},
|
2530
|
-
get _names() {
|
2531
|
-
return _names;
|
2532
|
-
},
|
2533
|
-
set _names(value) {
|
2534
|
-
_names = value;
|
2535
|
-
},
|
2536
|
-
get _formState() {
|
2537
|
-
return _formState;
|
2538
|
-
},
|
2539
|
-
set _formState(value) {
|
2540
|
-
_formState = value;
|
2541
|
-
},
|
2542
|
-
get _options() {
|
2543
|
-
return _options;
|
2544
|
-
},
|
2545
|
-
set _options(value) {
|
2546
|
-
_options = {
|
2547
|
-
..._options,
|
2548
|
-
...value,
|
2549
|
-
};
|
2550
|
-
},
|
2551
|
-
},
|
2552
|
-
trigger,
|
2553
|
-
register,
|
2554
|
-
handleSubmit,
|
2555
|
-
watch,
|
2556
|
-
setValue,
|
2557
|
-
getValues,
|
2558
|
-
reset,
|
2559
|
-
resetField,
|
2560
|
-
clearErrors,
|
2561
|
-
unregister,
|
2562
|
-
setError,
|
2563
|
-
setFocus,
|
2564
|
-
getFieldState,
|
2563
|
+
swap: React.useCallback(swap, [updateValues, name, control]),
|
2564
|
+
move: React.useCallback(move, [updateValues, name, control]),
|
2565
|
+
prepend: React.useCallback(prepend, [updateValues, name, control]),
|
2566
|
+
append: React.useCallback(append, [updateValues, name, control]),
|
2567
|
+
remove: React.useCallback(remove, [updateValues, name, control]),
|
2568
|
+
insert: React.useCallback(insert$1, [updateValues, name, control]),
|
2569
|
+
update: React.useCallback(update, [updateValues, name, control]),
|
2570
|
+
replace: React.useCallback(replace, [updateValues, name, control]),
|
2571
|
+
fields: React.useMemo(() => fields.map((field, index) => ({
|
2572
|
+
...field,
|
2573
|
+
[keyName]: ids.current[index] || generateId(),
|
2574
|
+
})), [fields, keyName]),
|
2565
2575
|
};
|
2566
2576
|
}
|
2567
2577
|
|
@@ -2617,20 +2627,17 @@ function useForm(props = {}) {
|
|
2617
2627
|
});
|
2618
2628
|
if (!_formControl.current) {
|
2619
2629
|
_formControl.current = {
|
2620
|
-
...createFormControl(props),
|
2630
|
+
...(props.control ? props.control : createFormControl(props)),
|
2621
2631
|
formState,
|
2622
2632
|
};
|
2623
2633
|
}
|
2624
2634
|
const control = _formControl.current.control;
|
2625
2635
|
control._options = props;
|
2626
|
-
|
2627
|
-
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
}
|
2632
|
-
},
|
2633
|
-
});
|
2636
|
+
React.useEffect(() => control._subscribe({
|
2637
|
+
formState: control._proxyFormState,
|
2638
|
+
callback: () => updateFormState({ ...control._formState }),
|
2639
|
+
reRenderRoot: true,
|
2640
|
+
}), [control]);
|
2634
2641
|
React.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
|
2635
2642
|
React.useEffect(() => {
|
2636
2643
|
if (control._proxyFormState.isDirty) {
|
@@ -2659,7 +2666,7 @@ function useForm(props = {}) {
|
|
2659
2666
|
}, [props.errors, control]);
|
2660
2667
|
React.useEffect(() => {
|
2661
2668
|
if (!control._state.mount) {
|
2662
|
-
control.
|
2669
|
+
control._setValid();
|
2663
2670
|
control._state.mount = true;
|
2664
2671
|
}
|
2665
2672
|
if (control._state.watch) {
|
@@ -2670,7 +2677,7 @@ function useForm(props = {}) {
|
|
2670
2677
|
});
|
2671
2678
|
React.useEffect(() => {
|
2672
2679
|
props.shouldUnregister &&
|
2673
|
-
control._subjects.
|
2680
|
+
control._subjects.state.next({
|
2674
2681
|
values: control._getWatch(),
|
2675
2682
|
});
|
2676
2683
|
}, [props.shouldUnregister, control]);
|
@@ -2678,5 +2685,5 @@ function useForm(props = {}) {
|
|
2678
2685
|
return _formControl.current;
|
2679
2686
|
}
|
2680
2687
|
|
2681
|
-
export { Controller, Form, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
2688
|
+
export { Controller, Form, FormProvider, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
2682
2689
|
//# sourceMappingURL=index.esm.mjs.map
|