react-hook-form 7.54.2 → 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/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.mjs +1358 -1339
- 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/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/react-server.esm.mjs +1727 -4
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/form.d.ts +49 -11
- package/dist/types/form.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;
|
@@ -502,7 +461,7 @@ function useController(props) {
|
|
502
461
|
};
|
503
462
|
}, [name, control, isArrayField, shouldUnregister]);
|
504
463
|
React.useEffect(() => {
|
505
|
-
control.
|
464
|
+
control._setDisabledField({
|
506
465
|
disabled,
|
507
466
|
fields: control._fields,
|
508
467
|
name,
|
@@ -684,67 +643,70 @@ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => va
|
|
684
643
|
}
|
685
644
|
: {};
|
686
645
|
|
687
|
-
var
|
688
|
-
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
|
689
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
690
|
-
const r = (Math.random() * 16 + d) % 16 | 0;
|
691
|
-
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
692
|
-
});
|
693
|
-
};
|
694
|
-
|
695
|
-
var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
|
696
|
-
? options.focusName ||
|
697
|
-
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
698
|
-
: '';
|
646
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
699
647
|
|
700
|
-
var
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
}
|
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
|
+
};
|
707
675
|
|
708
|
-
var
|
709
|
-
(_names.watchAll ||
|
710
|
-
_names.watch.has(name) ||
|
711
|
-
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
|
712
|
-
/^\.\w+/.test(name.slice(watchName.length))));
|
676
|
+
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
713
677
|
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
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;
|
736
703
|
}
|
737
704
|
}
|
738
705
|
}
|
739
|
-
return;
|
740
|
-
}
|
706
|
+
return true;
|
707
|
+
}
|
741
708
|
|
742
|
-
var
|
743
|
-
const fieldArrayErrors = convertToArrayPayload(get(errors, name));
|
744
|
-
set(fieldArrayErrors, 'root', error[name]);
|
745
|
-
set(errors, name, fieldArrayErrors);
|
746
|
-
return errors;
|
747
|
-
};
|
709
|
+
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
748
710
|
|
749
711
|
var isFileInput = (element) => element.type === 'file';
|
750
712
|
|
@@ -759,11 +721,99 @@ var isHTMLElement = (value) => {
|
|
759
721
|
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
|
760
722
|
};
|
761
723
|
|
762
|
-
var
|
724
|
+
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
763
725
|
|
764
726
|
var isRadioInput = (element) => element.type === 'radio';
|
765
727
|
|
766
|
-
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));
|
767
817
|
|
768
818
|
const defaultResult = {
|
769
819
|
value: false,
|
@@ -790,6 +840,20 @@ var getCheckboxValue = (options) => {
|
|
790
840
|
return defaultResult;
|
791
841
|
};
|
792
842
|
|
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
|
+
|
793
857
|
const defaultReturn = {
|
794
858
|
isValid: false,
|
795
859
|
value: null,
|
@@ -803,6 +867,182 @@ var getRadioValue = (options) => Array.isArray(options)
|
|
803
867
|
: previous, defaultReturn)
|
804
868
|
: defaultReturn;
|
805
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
|
+
|
806
1046
|
function getValidateError(result, ref, type = 'validate') {
|
807
1047
|
if (isMessage(result) ||
|
808
1048
|
(Array.isArray(result) && result.every(isMessage)) ||
|
@@ -1001,848 +1241,301 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
|
|
1001
1241
|
return error;
|
1002
1242
|
};
|
1003
1243
|
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
|
1010
|
-
|
1011
|
-
function insert(data, index, value) {
|
1012
|
-
return [
|
1013
|
-
...data.slice(0, index),
|
1014
|
-
...convertToArrayPayload(value),
|
1015
|
-
...data.slice(index),
|
1016
|
-
];
|
1017
|
-
}
|
1018
|
-
|
1019
|
-
var moveArrayAt = (data, from, to) => {
|
1020
|
-
if (!Array.isArray(data)) {
|
1021
|
-
return [];
|
1022
|
-
}
|
1023
|
-
if (isUndefined(data[to])) {
|
1024
|
-
data[to] = undefined;
|
1025
|
-
}
|
1026
|
-
data.splice(to, 0, data.splice(from, 1)[0]);
|
1027
|
-
return data;
|
1028
|
-
};
|
1029
|
-
|
1030
|
-
var prependAt = (data, value) => [
|
1031
|
-
...convertToArrayPayload(value),
|
1032
|
-
...convertToArrayPayload(data),
|
1033
|
-
];
|
1034
|
-
|
1035
|
-
function removeAtIndexes(data, indexes) {
|
1036
|
-
let i = 0;
|
1037
|
-
const temp = [...data];
|
1038
|
-
for (const index of indexes) {
|
1039
|
-
temp.splice(index - i, 1);
|
1040
|
-
i++;
|
1041
|
-
}
|
1042
|
-
return compact(temp).length ? temp : [];
|
1043
|
-
}
|
1044
|
-
var removeArrayAt = (data, index) => isUndefined(index)
|
1045
|
-
? []
|
1046
|
-
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
1047
|
-
|
1048
|
-
var swapArrayAt = (data, indexA, indexB) => {
|
1049
|
-
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
1244
|
+
const defaultOptions = {
|
1245
|
+
mode: VALIDATION_MODE.onSubmit,
|
1246
|
+
reValidateMode: VALIDATION_MODE.onChange,
|
1247
|
+
shouldFocusError: true,
|
1050
1248
|
};
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
while (index < length) {
|
1056
|
-
object = isUndefined(object) ? index++ : object[updatePath[index++]];
|
1057
|
-
}
|
1058
|
-
return object;
|
1059
|
-
}
|
1060
|
-
function isEmptyArray(obj) {
|
1061
|
-
for (const key in obj) {
|
1062
|
-
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
1063
|
-
return false;
|
1064
|
-
}
|
1065
|
-
}
|
1066
|
-
return true;
|
1067
|
-
}
|
1068
|
-
function unset(object, path) {
|
1069
|
-
const paths = Array.isArray(path)
|
1070
|
-
? path
|
1071
|
-
: isKey(path)
|
1072
|
-
? [path]
|
1073
|
-
: stringToPath(path);
|
1074
|
-
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
1075
|
-
const index = paths.length - 1;
|
1076
|
-
const key = paths[index];
|
1077
|
-
if (childObject) {
|
1078
|
-
delete childObject[key];
|
1079
|
-
}
|
1080
|
-
if (index !== 0 &&
|
1081
|
-
((isObject(childObject) && isEmptyObject(childObject)) ||
|
1082
|
-
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
1083
|
-
unset(object, paths.slice(0, -1));
|
1084
|
-
}
|
1085
|
-
return object;
|
1086
|
-
}
|
1087
|
-
|
1088
|
-
var updateAt = (fieldValues, index, value) => {
|
1089
|
-
fieldValues[index] = value;
|
1090
|
-
return fieldValues;
|
1091
|
-
};
|
1092
|
-
|
1093
|
-
/**
|
1094
|
-
* 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)
|
1095
|
-
*
|
1096
|
-
* @remarks
|
1097
|
-
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
1098
|
-
*
|
1099
|
-
* @param props - useFieldArray props
|
1100
|
-
*
|
1101
|
-
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
1102
|
-
*
|
1103
|
-
* @example
|
1104
|
-
* ```tsx
|
1105
|
-
* function App() {
|
1106
|
-
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
1107
|
-
* defaultValues: {
|
1108
|
-
* test: []
|
1109
|
-
* }
|
1110
|
-
* });
|
1111
|
-
* const { fields, append } = useFieldArray({
|
1112
|
-
* control,
|
1113
|
-
* name: "test"
|
1114
|
-
* });
|
1115
|
-
*
|
1116
|
-
* return (
|
1117
|
-
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
1118
|
-
* {fields.map((item, index) => (
|
1119
|
-
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
1120
|
-
* ))}
|
1121
|
-
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
1122
|
-
* append
|
1123
|
-
* </button>
|
1124
|
-
* <input type="submit" />
|
1125
|
-
* </form>
|
1126
|
-
* );
|
1127
|
-
* }
|
1128
|
-
* ```
|
1129
|
-
*/
|
1130
|
-
function useFieldArray(props) {
|
1131
|
-
const methods = useFormContext();
|
1132
|
-
const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
|
1133
|
-
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
1134
|
-
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
1135
|
-
const _fieldIds = React.useRef(fields);
|
1136
|
-
const _name = React.useRef(name);
|
1137
|
-
const _actioned = React.useRef(false);
|
1138
|
-
_name.current = name;
|
1139
|
-
_fieldIds.current = fields;
|
1140
|
-
control._names.array.add(name);
|
1141
|
-
rules &&
|
1142
|
-
control.register(name, rules);
|
1143
|
-
useSubscribe({
|
1144
|
-
next: ({ values, name: fieldArrayName, }) => {
|
1145
|
-
if (fieldArrayName === _name.current || !fieldArrayName) {
|
1146
|
-
const fieldValues = get(values, _name.current);
|
1147
|
-
if (Array.isArray(fieldValues)) {
|
1148
|
-
setFields(fieldValues);
|
1149
|
-
ids.current = fieldValues.map(generateId);
|
1150
|
-
}
|
1151
|
-
}
|
1152
|
-
},
|
1153
|
-
subject: control._subjects.array,
|
1154
|
-
});
|
1155
|
-
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
1156
|
-
_actioned.current = true;
|
1157
|
-
control._updateFieldArray(name, updatedFieldArrayValues);
|
1158
|
-
}, [control, name]);
|
1159
|
-
const append = (value, options) => {
|
1160
|
-
const appendValue = convertToArrayPayload(cloneObject(value));
|
1161
|
-
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
|
1162
|
-
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
|
1163
|
-
ids.current = appendAt(ids.current, appendValue.map(generateId));
|
1164
|
-
updateValues(updatedFieldArrayValues);
|
1165
|
-
setFields(updatedFieldArrayValues);
|
1166
|
-
control._updateFieldArray(name, updatedFieldArrayValues, appendAt, {
|
1167
|
-
argA: fillEmptyArray(value),
|
1168
|
-
});
|
1249
|
+
function createFormControl(props = {}) {
|
1250
|
+
let _options = {
|
1251
|
+
...defaultOptions,
|
1252
|
+
...props,
|
1169
1253
|
};
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
}
|
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,
|
1180
1268
|
};
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
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,
|
1191
1280
|
};
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
setFields(updatedFieldArrayValues);
|
1199
|
-
control._updateFieldArray(name, updatedFieldArrayValues, insert, {
|
1200
|
-
argA: index,
|
1201
|
-
argB: fillEmptyArray(value),
|
1202
|
-
});
|
1281
|
+
let _names = {
|
1282
|
+
mount: new Set(),
|
1283
|
+
disabled: new Set(),
|
1284
|
+
unMount: new Set(),
|
1285
|
+
array: new Set(),
|
1286
|
+
watch: new Set(),
|
1203
1287
|
};
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
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,
|
1214
1298
|
};
|
1215
|
-
|
1216
|
-
|
1217
|
-
moveArrayAt(updatedFieldArrayValues, from, to);
|
1218
|
-
moveArrayAt(ids.current, from, to);
|
1219
|
-
updateValues(updatedFieldArrayValues);
|
1220
|
-
setFields(updatedFieldArrayValues);
|
1221
|
-
control._updateFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
|
1222
|
-
argA: from,
|
1223
|
-
argB: to,
|
1224
|
-
}, false);
|
1299
|
+
let _proxySubscribeFormState = {
|
1300
|
+
..._proxyFormState,
|
1225
1301
|
};
|
1226
|
-
const
|
1227
|
-
|
1228
|
-
|
1229
|
-
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
1230
|
-
updateValues(updatedFieldArrayValues);
|
1231
|
-
setFields([...updatedFieldArrayValues]);
|
1232
|
-
control._updateFieldArray(name, updatedFieldArrayValues, updateAt, {
|
1233
|
-
argA: index,
|
1234
|
-
argB: updateValue,
|
1235
|
-
}, true, false);
|
1302
|
+
const _subjects = {
|
1303
|
+
array: createSubject(),
|
1304
|
+
state: createSubject(),
|
1236
1305
|
};
|
1237
|
-
const
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
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);
|
1243
1312
|
};
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
const error = get(result.errors, name);
|
1256
|
-
const existingError = get(control._formState.errors, name);
|
1257
|
-
if (existingError
|
1258
|
-
? (!error && existingError.type) ||
|
1259
|
-
(error &&
|
1260
|
-
(existingError.type !== error.type ||
|
1261
|
-
existingError.message !== error.message))
|
1262
|
-
: error && error.type) {
|
1263
|
-
error
|
1264
|
-
? set(control._formState.errors, name, error)
|
1265
|
-
: unset(control._formState.errors, name);
|
1266
|
-
control._subjects.state.next({
|
1267
|
-
errors: control._formState.errors,
|
1268
|
-
});
|
1269
|
-
}
|
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,
|
1270
1324
|
});
|
1271
1325
|
}
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
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);
|
1282
1339
|
}
|
1283
|
-
}
|
1340
|
+
});
|
1341
|
+
_subjects.state.next({
|
1342
|
+
validatingFields: _formState.validatingFields,
|
1343
|
+
isValidating: !isEmptyObject(_formState.validatingFields),
|
1344
|
+
});
|
1284
1345
|
}
|
1285
|
-
control._subjects.values.next({
|
1286
|
-
name,
|
1287
|
-
values: { ...control._formValues },
|
1288
|
-
});
|
1289
|
-
control._names.focus &&
|
1290
|
-
iterateFieldsByAction(control._fields, (ref, key) => {
|
1291
|
-
if (control._names.focus &&
|
1292
|
-
key.startsWith(control._names.focus) &&
|
1293
|
-
ref.focus) {
|
1294
|
-
ref.focus();
|
1295
|
-
return 1;
|
1296
|
-
}
|
1297
|
-
return;
|
1298
|
-
});
|
1299
|
-
control._names.focus = '';
|
1300
|
-
control._updateValid();
|
1301
|
-
_actioned.current = false;
|
1302
|
-
}, [fields, name, control]);
|
1303
|
-
React.useEffect(() => {
|
1304
|
-
!get(control._formValues, name) && control._updateFieldArray(name);
|
1305
|
-
return () => {
|
1306
|
-
(control._options.shouldUnregister || shouldUnregister) &&
|
1307
|
-
control.unregister(name);
|
1308
|
-
};
|
1309
|
-
}, [name, control, keyName, shouldUnregister]);
|
1310
|
-
return {
|
1311
|
-
swap: React.useCallback(swap, [updateValues, name, control]),
|
1312
|
-
move: React.useCallback(move, [updateValues, name, control]),
|
1313
|
-
prepend: React.useCallback(prepend, [updateValues, name, control]),
|
1314
|
-
append: React.useCallback(append, [updateValues, name, control]),
|
1315
|
-
remove: React.useCallback(remove, [updateValues, name, control]),
|
1316
|
-
insert: React.useCallback(insert$1, [updateValues, name, control]),
|
1317
|
-
update: React.useCallback(update, [updateValues, name, control]),
|
1318
|
-
replace: React.useCallback(replace, [updateValues, name, control]),
|
1319
|
-
fields: React.useMemo(() => fields.map((field, index) => ({
|
1320
|
-
...field,
|
1321
|
-
[keyName]: ids.current[index] || generateId(),
|
1322
|
-
})), [fields, keyName]),
|
1323
1346
|
};
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
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);
|
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
|
+
});
|
1377
|
+
}
|
1378
|
+
else {
|
1379
|
+
set(_formValues, name, values);
|
1331
1380
|
}
|
1332
1381
|
};
|
1333
|
-
const
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
},
|
1339
|
-
};
|
1340
|
-
};
|
1341
|
-
const unsubscribe = () => {
|
1342
|
-
_observers = [];
|
1382
|
+
const updateErrors = (name, error) => {
|
1383
|
+
set(_formState.errors, name, error);
|
1384
|
+
_subjects.state.next({
|
1385
|
+
errors: _formState.errors,
|
1386
|
+
});
|
1343
1387
|
};
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
unsubscribe,
|
1388
|
+
const _setErrors = (errors) => {
|
1389
|
+
_formState.errors = errors;
|
1390
|
+
_subjects.state.next({
|
1391
|
+
errors: _formState.errors,
|
1392
|
+
isValid: false,
|
1393
|
+
});
|
1351
1394
|
};
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
}
|
1363
|
-
const keys1 = Object.keys(object1);
|
1364
|
-
const keys2 = Object.keys(object2);
|
1365
|
-
if (keys1.length !== keys2.length) {
|
1366
|
-
return false;
|
1367
|
-
}
|
1368
|
-
for (const key of keys1) {
|
1369
|
-
const val1 = object1[key];
|
1370
|
-
if (!keys2.includes(key)) {
|
1371
|
-
return false;
|
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();
|
1372
1405
|
}
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1406
|
+
};
|
1407
|
+
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
1408
|
+
let shouldUpdateField = false;
|
1409
|
+
let isPreviousDirty = false;
|
1410
|
+
const output = {
|
1411
|
+
name,
|
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
|
+
}
|
1381
1446
|
}
|
1447
|
+
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
1382
1448
|
}
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
var objectHasFunction = (data) => {
|
1394
|
-
for (const key in data) {
|
1395
|
-
if (isFunction(data[key])) {
|
1396
|
-
return true;
|
1449
|
+
return shouldUpdateField ? output : {};
|
1450
|
+
};
|
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);
|
1397
1459
|
}
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
if (isObject(data) || isParentNodeArray) {
|
1405
|
-
for (const key in data) {
|
1406
|
-
if (Array.isArray(data[key]) ||
|
1407
|
-
(isObject(data[key]) && !objectHasFunction(data[key]))) {
|
1408
|
-
fields[key] = Array.isArray(data[key]) ? [] : {};
|
1409
|
-
markFieldsDirty(data[key], fields[key]);
|
1410
|
-
}
|
1411
|
-
else if (!isNullOrUndefined(data[key])) {
|
1412
|
-
fields[key] = true;
|
1413
|
-
}
|
1460
|
+
else {
|
1461
|
+
clearTimeout(timer);
|
1462
|
+
delayErrorCallback = null;
|
1463
|
+
error
|
1464
|
+
? set(_formState.errors, name, error)
|
1465
|
+
: unset(_formState.errors, name);
|
1414
1466
|
}
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
}
|
1430
|
-
else {
|
1431
|
-
getDirtyFieldsFromDefaultValues(data[key], isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
|
1432
|
-
}
|
1433
|
-
}
|
1434
|
-
else {
|
1435
|
-
dirtyFieldsFromValues[key] = !deepEqual(data[key], formValues[key]);
|
1436
|
-
}
|
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);
|
1437
1481
|
}
|
1438
|
-
}
|
1439
|
-
return dirtyFieldsFromValues;
|
1440
|
-
}
|
1441
|
-
var getDirtyFields = (defaultValues, formValues) => getDirtyFieldsFromDefaultValues(defaultValues, formValues, markFieldsDirty(formValues));
|
1442
|
-
|
1443
|
-
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
1444
|
-
? value
|
1445
|
-
: valueAsNumber
|
1446
|
-
? value === ''
|
1447
|
-
? NaN
|
1448
|
-
: value
|
1449
|
-
? +value
|
1450
|
-
: value
|
1451
|
-
: valueAsDate && isString(value)
|
1452
|
-
? new Date(value)
|
1453
|
-
: setValueAs
|
1454
|
-
? setValueAs(value)
|
1455
|
-
: value;
|
1456
|
-
|
1457
|
-
function getFieldValue(_f) {
|
1458
|
-
const ref = _f.ref;
|
1459
|
-
if (isFileInput(ref)) {
|
1460
|
-
return ref.files;
|
1461
|
-
}
|
1462
|
-
if (isRadioInput(ref)) {
|
1463
|
-
return getRadioValue(_f.refs).value;
|
1464
|
-
}
|
1465
|
-
if (isMultipleSelect(ref)) {
|
1466
|
-
return [...ref.selectedOptions].map(({ value }) => value);
|
1467
|
-
}
|
1468
|
-
if (isCheckBoxInput(ref)) {
|
1469
|
-
return getCheckboxValue(_f.refs).value;
|
1470
|
-
}
|
1471
|
-
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
1472
|
-
}
|
1473
|
-
|
1474
|
-
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
1475
|
-
const fields = {};
|
1476
|
-
for (const name of fieldsNames) {
|
1477
|
-
const field = get(_fields, name);
|
1478
|
-
field && set(fields, name, field._f);
|
1479
|
-
}
|
1480
|
-
return {
|
1481
|
-
criteriaMode,
|
1482
|
-
names: [...fieldsNames],
|
1483
|
-
fields,
|
1484
|
-
shouldUseNativeValidation,
|
1485
|
-
};
|
1486
|
-
};
|
1487
|
-
|
1488
|
-
var getRuleValue = (rule) => isUndefined(rule)
|
1489
|
-
? rule
|
1490
|
-
: isRegex(rule)
|
1491
|
-
? rule.source
|
1492
|
-
: isObject(rule)
|
1493
|
-
? isRegex(rule.value)
|
1494
|
-
? rule.value.source
|
1495
|
-
: rule.value
|
1496
|
-
: rule;
|
1497
|
-
|
1498
|
-
const ASYNC_FUNCTION = 'AsyncFunction';
|
1499
|
-
var hasPromiseValidation = (fieldReference) => !!fieldReference &&
|
1500
|
-
!!fieldReference.validate &&
|
1501
|
-
!!((isFunction(fieldReference.validate) &&
|
1502
|
-
fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
|
1503
|
-
(isObject(fieldReference.validate) &&
|
1504
|
-
Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
|
1505
|
-
|
1506
|
-
var hasValidation = (options) => options.mount &&
|
1507
|
-
(options.required ||
|
1508
|
-
options.min ||
|
1509
|
-
options.max ||
|
1510
|
-
options.maxLength ||
|
1511
|
-
options.minLength ||
|
1512
|
-
options.pattern ||
|
1513
|
-
options.validate);
|
1514
|
-
|
1515
|
-
function schemaErrorLookup(errors, _fields, name) {
|
1516
|
-
const error = get(errors, name);
|
1517
|
-
if (error || isKey(name)) {
|
1518
|
-
return {
|
1519
|
-
error,
|
1520
|
-
name,
|
1521
|
-
};
|
1522
|
-
}
|
1523
|
-
const names = name.split('.');
|
1524
|
-
while (names.length) {
|
1525
|
-
const fieldName = names.join('.');
|
1526
|
-
const field = get(_fields, fieldName);
|
1527
|
-
const foundError = get(errors, fieldName);
|
1528
|
-
if (field && !Array.isArray(field) && name !== fieldName) {
|
1529
|
-
return { name };
|
1530
|
-
}
|
1531
|
-
if (foundError && foundError.type) {
|
1532
|
-
return {
|
1533
|
-
name: fieldName,
|
1534
|
-
error: foundError,
|
1535
|
-
};
|
1536
|
-
}
|
1537
|
-
names.pop();
|
1538
|
-
}
|
1539
|
-
return {
|
1540
|
-
name,
|
1541
|
-
};
|
1542
|
-
}
|
1543
|
-
|
1544
|
-
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
|
1545
|
-
if (mode.isOnAll) {
|
1546
|
-
return false;
|
1547
|
-
}
|
1548
|
-
else if (!isSubmitted && mode.isOnTouch) {
|
1549
|
-
return !(isTouched || isBlurEvent);
|
1550
|
-
}
|
1551
|
-
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
|
1552
|
-
return !isBlurEvent;
|
1553
|
-
}
|
1554
|
-
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
|
1555
|
-
return isBlurEvent;
|
1556
|
-
}
|
1557
|
-
return true;
|
1558
|
-
};
|
1559
|
-
|
1560
|
-
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
1561
|
-
|
1562
|
-
const defaultOptions = {
|
1563
|
-
mode: VALIDATION_MODE.onSubmit,
|
1564
|
-
reValidateMode: VALIDATION_MODE.onChange,
|
1565
|
-
shouldFocusError: true,
|
1566
|
-
};
|
1567
|
-
function createFormControl(props = {}) {
|
1568
|
-
let _options = {
|
1569
|
-
...defaultOptions,
|
1570
|
-
...props,
|
1571
1482
|
};
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
isSubmitted: false,
|
1578
|
-
isSubmitting: false,
|
1579
|
-
isSubmitSuccessful: false,
|
1580
|
-
isValid: false,
|
1581
|
-
touchedFields: {},
|
1582
|
-
dirtyFields: {},
|
1583
|
-
validatingFields: {},
|
1584
|
-
errors: _options.errors || {},
|
1585
|
-
disabled: _options.disabled || false,
|
1586
|
-
};
|
1587
|
-
let _fields = {};
|
1588
|
-
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
|
1589
|
-
? cloneObject(_options.defaultValues || _options.values) || {}
|
1590
|
-
: {};
|
1591
|
-
let _formValues = _options.shouldUnregister
|
1592
|
-
? {}
|
1593
|
-
: cloneObject(_defaultValues);
|
1594
|
-
let _state = {
|
1595
|
-
action: false,
|
1596
|
-
mount: false,
|
1597
|
-
watch: false,
|
1598
|
-
};
|
1599
|
-
let _names = {
|
1600
|
-
mount: new Set(),
|
1601
|
-
disabled: new Set(),
|
1602
|
-
unMount: new Set(),
|
1603
|
-
array: new Set(),
|
1604
|
-
watch: new Set(),
|
1605
|
-
};
|
1606
|
-
let delayErrorCallback;
|
1607
|
-
let timer = 0;
|
1608
|
-
const _proxyFormState = {
|
1609
|
-
isDirty: false,
|
1610
|
-
dirtyFields: false,
|
1611
|
-
validatingFields: false,
|
1612
|
-
touchedFields: false,
|
1613
|
-
isValidating: false,
|
1614
|
-
isValid: false,
|
1615
|
-
errors: false,
|
1616
|
-
};
|
1617
|
-
const _subjects = {
|
1618
|
-
values: createSubject(),
|
1619
|
-
array: createSubject(),
|
1620
|
-
state: createSubject(),
|
1621
|
-
};
|
1622
|
-
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
1623
|
-
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
1624
|
-
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
1625
|
-
const debounce = (callback) => (wait) => {
|
1626
|
-
clearTimeout(timer);
|
1627
|
-
timer = setTimeout(callback, wait);
|
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;
|
1628
1488
|
};
|
1629
|
-
const
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
});
|
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);
|
1638
1497
|
}
|
1639
1498
|
}
|
1499
|
+
else {
|
1500
|
+
_formState.errors = errors;
|
1501
|
+
}
|
1502
|
+
return errors;
|
1640
1503
|
};
|
1641
|
-
const
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
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));
|
1649
1533
|
}
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
isValidating: !isEmptyObject(_formState.validatingFields),
|
1654
|
-
});
|
1534
|
+
!isEmptyObject(fieldValue) &&
|
1535
|
+
(await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
|
1536
|
+
}
|
1655
1537
|
}
|
1656
|
-
|
1657
|
-
const _updateFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
1658
|
-
if (args && method && !_options.disabled) {
|
1659
|
-
_state.action = true;
|
1660
|
-
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
|
1661
|
-
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
1662
|
-
shouldSetValues && set(_fields, name, fieldValues);
|
1663
|
-
}
|
1664
|
-
if (shouldUpdateFieldsAndState &&
|
1665
|
-
Array.isArray(get(_formState.errors, name))) {
|
1666
|
-
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
1667
|
-
shouldSetValues && set(_formState.errors, name, errors);
|
1668
|
-
unsetEmptyArray(_formState.errors, name);
|
1669
|
-
}
|
1670
|
-
if (_proxyFormState.touchedFields &&
|
1671
|
-
shouldUpdateFieldsAndState &&
|
1672
|
-
Array.isArray(get(_formState.touchedFields, name))) {
|
1673
|
-
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
1674
|
-
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
1675
|
-
}
|
1676
|
-
if (_proxyFormState.dirtyFields) {
|
1677
|
-
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
|
1678
|
-
}
|
1679
|
-
_subjects.state.next({
|
1680
|
-
name,
|
1681
|
-
isDirty: _getDirty(name, values),
|
1682
|
-
dirtyFields: _formState.dirtyFields,
|
1683
|
-
errors: _formState.errors,
|
1684
|
-
isValid: _formState.isValid,
|
1685
|
-
});
|
1686
|
-
}
|
1687
|
-
else {
|
1688
|
-
set(_formValues, name, values);
|
1689
|
-
}
|
1690
|
-
};
|
1691
|
-
const updateErrors = (name, error) => {
|
1692
|
-
set(_formState.errors, name, error);
|
1693
|
-
_subjects.state.next({
|
1694
|
-
errors: _formState.errors,
|
1695
|
-
});
|
1696
|
-
};
|
1697
|
-
const _setErrors = (errors) => {
|
1698
|
-
_formState.errors = errors;
|
1699
|
-
_subjects.state.next({
|
1700
|
-
errors: _formState.errors,
|
1701
|
-
isValid: false,
|
1702
|
-
});
|
1703
|
-
};
|
1704
|
-
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
|
1705
|
-
const field = get(_fields, name);
|
1706
|
-
if (field) {
|
1707
|
-
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
|
1708
|
-
isUndefined(defaultValue) ||
|
1709
|
-
(ref && ref.defaultChecked) ||
|
1710
|
-
shouldSkipSetValueAs
|
1711
|
-
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
1712
|
-
: setFieldValue(name, defaultValue);
|
1713
|
-
_state.mount && _updateValid();
|
1714
|
-
}
|
1715
|
-
};
|
1716
|
-
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
1717
|
-
let shouldUpdateField = false;
|
1718
|
-
let isPreviousDirty = false;
|
1719
|
-
const output = {
|
1720
|
-
name,
|
1721
|
-
};
|
1722
|
-
if (!_options.disabled) {
|
1723
|
-
const disabledField = !!(get(_fields, name) &&
|
1724
|
-
get(_fields, name)._f &&
|
1725
|
-
get(_fields, name)._f.disabled);
|
1726
|
-
if (!isBlurEvent || shouldDirty) {
|
1727
|
-
if (_proxyFormState.isDirty) {
|
1728
|
-
isPreviousDirty = _formState.isDirty;
|
1729
|
-
_formState.isDirty = output.isDirty = _getDirty();
|
1730
|
-
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
1731
|
-
}
|
1732
|
-
const isCurrentFieldPristine = disabledField || deepEqual(get(_defaultValues, name), fieldValue);
|
1733
|
-
isPreviousDirty = !!(!disabledField && get(_formState.dirtyFields, name));
|
1734
|
-
isCurrentFieldPristine || disabledField
|
1735
|
-
? unset(_formState.dirtyFields, name)
|
1736
|
-
: set(_formState.dirtyFields, name, true);
|
1737
|
-
output.dirtyFields = _formState.dirtyFields;
|
1738
|
-
shouldUpdateField =
|
1739
|
-
shouldUpdateField ||
|
1740
|
-
(_proxyFormState.dirtyFields &&
|
1741
|
-
isPreviousDirty !== !isCurrentFieldPristine);
|
1742
|
-
}
|
1743
|
-
if (isBlurEvent) {
|
1744
|
-
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1745
|
-
if (!isPreviousFieldTouched) {
|
1746
|
-
set(_formState.touchedFields, name, isBlurEvent);
|
1747
|
-
output.touchedFields = _formState.touchedFields;
|
1748
|
-
shouldUpdateField =
|
1749
|
-
shouldUpdateField ||
|
1750
|
-
(_proxyFormState.touchedFields &&
|
1751
|
-
isPreviousFieldTouched !== isBlurEvent);
|
1752
|
-
}
|
1753
|
-
}
|
1754
|
-
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
1755
|
-
}
|
1756
|
-
return shouldUpdateField ? output : {};
|
1757
|
-
};
|
1758
|
-
const shouldRenderByError = (name, isValid, error, fieldState) => {
|
1759
|
-
const previousFieldError = get(_formState.errors, name);
|
1760
|
-
const shouldUpdateValid = _proxyFormState.isValid &&
|
1761
|
-
isBoolean(isValid) &&
|
1762
|
-
_formState.isValid !== isValid;
|
1763
|
-
if (_options.delayError && error) {
|
1764
|
-
delayErrorCallback = debounce(() => updateErrors(name, error));
|
1765
|
-
delayErrorCallback(_options.delayError);
|
1766
|
-
}
|
1767
|
-
else {
|
1768
|
-
clearTimeout(timer);
|
1769
|
-
delayErrorCallback = null;
|
1770
|
-
error
|
1771
|
-
? set(_formState.errors, name, error)
|
1772
|
-
: unset(_formState.errors, name);
|
1773
|
-
}
|
1774
|
-
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
1775
|
-
!isEmptyObject(fieldState) ||
|
1776
|
-
shouldUpdateValid) {
|
1777
|
-
const updatedFormState = {
|
1778
|
-
...fieldState,
|
1779
|
-
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
1780
|
-
errors: _formState.errors,
|
1781
|
-
name,
|
1782
|
-
};
|
1783
|
-
_formState = {
|
1784
|
-
..._formState,
|
1785
|
-
...updatedFormState,
|
1786
|
-
};
|
1787
|
-
_subjects.state.next(updatedFormState);
|
1788
|
-
}
|
1789
|
-
};
|
1790
|
-
const _executeSchema = async (name) => {
|
1791
|
-
_updateIsValidating(name, true);
|
1792
|
-
const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
|
1793
|
-
_updateIsValidating(name);
|
1794
|
-
return result;
|
1795
|
-
};
|
1796
|
-
const executeSchemaAndUpdateState = async (names) => {
|
1797
|
-
const { errors } = await _executeSchema(names);
|
1798
|
-
if (names) {
|
1799
|
-
for (const name of names) {
|
1800
|
-
const error = get(errors, name);
|
1801
|
-
error
|
1802
|
-
? set(_formState.errors, name, error)
|
1803
|
-
: unset(_formState.errors, name);
|
1804
|
-
}
|
1805
|
-
}
|
1806
|
-
else {
|
1807
|
-
_formState.errors = errors;
|
1808
|
-
}
|
1809
|
-
return errors;
|
1810
|
-
};
|
1811
|
-
const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
|
1812
|
-
valid: true,
|
1813
|
-
}) => {
|
1814
|
-
for (const name in fields) {
|
1815
|
-
const field = fields[name];
|
1816
|
-
if (field) {
|
1817
|
-
const { _f, ...fieldValue } = field;
|
1818
|
-
if (_f) {
|
1819
|
-
const isFieldArrayRoot = _names.array.has(_f.name);
|
1820
|
-
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
|
1821
|
-
if (isPromiseFunction && _proxyFormState.validatingFields) {
|
1822
|
-
_updateIsValidating([name], true);
|
1823
|
-
}
|
1824
|
-
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
|
1825
|
-
if (isPromiseFunction && _proxyFormState.validatingFields) {
|
1826
|
-
_updateIsValidating([name]);
|
1827
|
-
}
|
1828
|
-
if (fieldError[_f.name]) {
|
1829
|
-
context.valid = false;
|
1830
|
-
if (shouldOnlyCheckValid) {
|
1831
|
-
break;
|
1832
|
-
}
|
1833
|
-
}
|
1834
|
-
!shouldOnlyCheckValid &&
|
1835
|
-
(get(fieldError, _f.name)
|
1836
|
-
? isFieldArrayRoot
|
1837
|
-
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
1838
|
-
: set(_formState.errors, _f.name, fieldError[_f.name])
|
1839
|
-
: unset(_formState.errors, _f.name));
|
1840
|
-
}
|
1841
|
-
!isEmptyObject(fieldValue) &&
|
1842
|
-
(await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
|
1843
|
-
}
|
1844
|
-
}
|
1845
|
-
return context.valid;
|
1538
|
+
return context.valid;
|
1846
1539
|
};
|
1847
1540
|
const _removeUnmounted = () => {
|
1848
1541
|
for (const name of _names.unMount) {
|
@@ -1903,7 +1596,7 @@ function createFormControl(props = {}) {
|
|
1903
1596
|
else {
|
1904
1597
|
fieldReference.ref.value = fieldValue;
|
1905
1598
|
if (!fieldReference.ref.type) {
|
1906
|
-
_subjects.
|
1599
|
+
_subjects.state.next({
|
1907
1600
|
name,
|
1908
1601
|
values: { ..._formValues },
|
1909
1602
|
});
|
@@ -1938,7 +1631,10 @@ function createFormControl(props = {}) {
|
|
1938
1631
|
name,
|
1939
1632
|
values: { ..._formValues },
|
1940
1633
|
});
|
1941
|
-
if ((_proxyFormState.isDirty ||
|
1634
|
+
if ((_proxyFormState.isDirty ||
|
1635
|
+
_proxyFormState.dirtyFields ||
|
1636
|
+
_proxySubscribeFormState.isDirty ||
|
1637
|
+
_proxySubscribeFormState.dirtyFields) &&
|
1942
1638
|
options.shouldDirty) {
|
1943
1639
|
_subjects.state.next({
|
1944
1640
|
name,
|
@@ -1953,7 +1649,7 @@ function createFormControl(props = {}) {
|
|
1953
1649
|
: setFieldValue(name, cloneValue, options);
|
1954
1650
|
}
|
1955
1651
|
isWatched(name, _names) && _subjects.state.next({ ..._formState });
|
1956
|
-
_subjects.
|
1652
|
+
_subjects.state.next({
|
1957
1653
|
name: _state.mount ? name : undefined,
|
1958
1654
|
values: { ..._formValues },
|
1959
1655
|
});
|
@@ -1964,7 +1660,6 @@ function createFormControl(props = {}) {
|
|
1964
1660
|
let name = target.name;
|
1965
1661
|
let isFieldValueUpdated = true;
|
1966
1662
|
const field = get(_fields, name);
|
1967
|
-
const getCurrentFieldValue = () => target.type ? getFieldValue(field._f) : getEventValue(event);
|
1968
1663
|
const _updateIsFieldValueUpdated = (fieldValue) => {
|
1969
1664
|
isFieldValueUpdated =
|
1970
1665
|
Number.isNaN(fieldValue) ||
|
@@ -1974,7 +1669,9 @@ function createFormControl(props = {}) {
|
|
1974
1669
|
if (field) {
|
1975
1670
|
let error;
|
1976
1671
|
let isValid;
|
1977
|
-
const fieldValue =
|
1672
|
+
const fieldValue = target.type
|
1673
|
+
? getFieldValue(field._f)
|
1674
|
+
: getEventValue(event);
|
1978
1675
|
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
1979
1676
|
const shouldSkipValidation = (!hasValidation(field._f) &&
|
1980
1677
|
!_options.resolver &&
|
@@ -1990,21 +1687,21 @@ function createFormControl(props = {}) {
|
|
1990
1687
|
else if (field._f.onChange) {
|
1991
1688
|
field._f.onChange(event);
|
1992
1689
|
}
|
1993
|
-
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent
|
1690
|
+
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
|
1994
1691
|
const shouldRender = !isEmptyObject(fieldState) || watched;
|
1995
1692
|
!isBlurEvent &&
|
1996
|
-
_subjects.
|
1693
|
+
_subjects.state.next({
|
1997
1694
|
name,
|
1998
1695
|
type: event.type,
|
1999
1696
|
values: { ..._formValues },
|
2000
1697
|
});
|
2001
1698
|
if (shouldSkipValidation) {
|
2002
|
-
if (_proxyFormState.isValid) {
|
1699
|
+
if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
|
2003
1700
|
if (_options.mode === 'onBlur' && isBlurEvent) {
|
2004
|
-
|
1701
|
+
_setValid();
|
2005
1702
|
}
|
2006
1703
|
else if (!isBlurEvent) {
|
2007
|
-
|
1704
|
+
_setValid();
|
2008
1705
|
}
|
2009
1706
|
}
|
2010
1707
|
return (shouldRender &&
|
@@ -2012,7 +1709,7 @@ function createFormControl(props = {}) {
|
|
2012
1709
|
}
|
2013
1710
|
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
|
2014
1711
|
if (_options.resolver) {
|
2015
|
-
const { errors } = await
|
1712
|
+
const { errors } = await _runSchema([name]);
|
2016
1713
|
_updateIsFieldValueUpdated(fieldValue);
|
2017
1714
|
if (isFieldValueUpdated) {
|
2018
1715
|
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
@@ -2031,7 +1728,8 @@ function createFormControl(props = {}) {
|
|
2031
1728
|
if (error) {
|
2032
1729
|
isValid = false;
|
2033
1730
|
}
|
2034
|
-
else if (_proxyFormState.isValid
|
1731
|
+
else if (_proxyFormState.isValid ||
|
1732
|
+
_proxySubscribeFormState.isValid) {
|
2035
1733
|
isValid = await executeBuiltInValidation(_fields, true);
|
2036
1734
|
}
|
2037
1735
|
}
|
@@ -2066,14 +1764,15 @@ function createFormControl(props = {}) {
|
|
2066
1764
|
const field = get(_fields, fieldName);
|
2067
1765
|
return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
|
2068
1766
|
}))).every(Boolean);
|
2069
|
-
!(!validationResult && !_formState.isValid) &&
|
1767
|
+
!(!validationResult && !_formState.isValid) && _setValid();
|
2070
1768
|
}
|
2071
1769
|
else {
|
2072
1770
|
validationResult = isValid = await executeBuiltInValidation(_fields);
|
2073
1771
|
}
|
2074
1772
|
_subjects.state.next({
|
2075
1773
|
...(!isString(name) ||
|
2076
|
-
(_proxyFormState.isValid
|
1774
|
+
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
1775
|
+
isValid !== _formState.isValid)
|
2077
1776
|
? {}
|
2078
1777
|
: { name }),
|
2079
1778
|
...(_options.resolver || !name ? { isValid } : {}),
|
@@ -2126,10 +1825,33 @@ function createFormControl(props = {}) {
|
|
2126
1825
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
2127
1826
|
};
|
2128
1827
|
const watch = (name, defaultValue) => isFunction(name)
|
2129
|
-
? _subjects.
|
1828
|
+
? _subjects.state.subscribe({
|
2130
1829
|
next: (payload) => name(_getWatch(undefined, defaultValue), payload),
|
2131
1830
|
})
|
2132
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
|
+
});
|
1841
|
+
}
|
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
|
+
};
|
2133
1855
|
const unregister = (name, options = {}) => {
|
2134
1856
|
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
2135
1857
|
_names.mount.delete(fieldName);
|
@@ -2147,409 +1869,709 @@ function createFormControl(props = {}) {
|
|
2147
1869
|
!options.keepDefaultValue &&
|
2148
1870
|
unset(_defaultValues, fieldName);
|
2149
1871
|
}
|
2150
|
-
_subjects.
|
1872
|
+
_subjects.state.next({
|
2151
1873
|
values: { ..._formValues },
|
2152
1874
|
});
|
2153
1875
|
_subjects.state.next({
|
2154
1876
|
..._formState,
|
2155
1877
|
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
2156
1878
|
});
|
2157
|
-
!options.keepIsValid &&
|
2158
|
-
};
|
2159
|
-
const
|
2160
|
-
if ((isBoolean(disabled) && _state.mount) ||
|
2161
|
-
!!disabled ||
|
2162
|
-
_names.disabled.has(name)) {
|
2163
|
-
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
2164
|
-
updateTouchAndDirty(name, getFieldValue(field ? field._f : get(fields, name)._f), false, false, true);
|
2165
|
-
}
|
1879
|
+
!options.keepIsValid && _setValid();
|
1880
|
+
};
|
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);
|
1887
|
+
}
|
1888
|
+
};
|
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
|
+
});
|
1910
|
+
}
|
1911
|
+
else {
|
1912
|
+
updateValidAndValue(name, true, options.value);
|
1913
|
+
}
|
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;
|
1946
|
+
}
|
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;
|
1968
|
+
}
|
1969
|
+
(_options.shouldUnregister || options.shouldUnregister) &&
|
1970
|
+
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
1971
|
+
_names.unMount.add(name);
|
1972
|
+
}
|
1973
|
+
},
|
1974
|
+
};
|
1975
|
+
};
|
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;
|
1988
|
+
});
|
1989
|
+
}
|
1990
|
+
}
|
1991
|
+
}, 0, false);
|
1992
|
+
}
|
1993
|
+
};
|
1994
|
+
const handleSubmit = (onValid, onInvalid) => async (e) => {
|
1995
|
+
let onValidError = undefined;
|
1996
|
+
if (e) {
|
1997
|
+
e.preventDefault && e.preventDefault();
|
1998
|
+
e.persist && e.persist();
|
1999
|
+
}
|
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: {},
|
2021
|
+
});
|
2022
|
+
try {
|
2023
|
+
await onValid(fieldValues, e);
|
2024
|
+
}
|
2025
|
+
catch (error) {
|
2026
|
+
onValidError = error;
|
2027
|
+
}
|
2028
|
+
}
|
2029
|
+
else {
|
2030
|
+
if (onInvalid) {
|
2031
|
+
await onInvalid({ ..._formState.errors }, e);
|
2032
|
+
}
|
2033
|
+
_focusError();
|
2034
|
+
setTimeout(_focusError);
|
2035
|
+
}
|
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,
|
2042
|
+
});
|
2043
|
+
if (onValidError) {
|
2044
|
+
throw onValidError;
|
2045
|
+
}
|
2046
|
+
};
|
2047
|
+
const resetField = (name, options = {}) => {
|
2048
|
+
if (get(_fields, name)) {
|
2049
|
+
if (isUndefined(options.defaultValue)) {
|
2050
|
+
setValue(name, cloneObject(get(_defaultValues, name)));
|
2051
|
+
}
|
2052
|
+
else {
|
2053
|
+
setValue(name, options.defaultValue);
|
2054
|
+
set(_defaultValues, name, cloneObject(options.defaultValue));
|
2055
|
+
}
|
2056
|
+
if (!options.keepTouched) {
|
2057
|
+
unset(_formState.touchedFields, name);
|
2058
|
+
}
|
2059
|
+
if (!options.keepDirty) {
|
2060
|
+
unset(_formState.dirtyFields, name);
|
2061
|
+
_formState.isDirty = options.defaultValue
|
2062
|
+
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
2063
|
+
: _getDirty();
|
2064
|
+
}
|
2065
|
+
if (!options.keepError) {
|
2066
|
+
unset(_formState.errors, name);
|
2067
|
+
_proxyFormState.isValid && _setValid();
|
2068
|
+
}
|
2069
|
+
_subjects.state.next({ ..._formState });
|
2070
|
+
}
|
2071
|
+
};
|
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;
|
2079
|
+
}
|
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
|
+
});
|
2123
|
+
}
|
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: '',
|
2132
|
+
};
|
2133
|
+
_state.mount =
|
2134
|
+
!_proxyFormState.isValid ||
|
2135
|
+
!!keepStateOptions.keepIsValid ||
|
2136
|
+
!!keepStateOptions.keepDirtyValues;
|
2137
|
+
_state.watch = !!_options.shouldUnregister;
|
2138
|
+
_subjects.state.next({
|
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,
|
2170
|
+
});
|
2171
|
+
};
|
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();
|
2187
|
+
}
|
2188
|
+
}
|
2189
|
+
};
|
2190
|
+
const _setFormState = (updatedFormState) => {
|
2191
|
+
_formState = {
|
2192
|
+
..._formState,
|
2193
|
+
...updatedFormState,
|
2194
|
+
};
|
2195
|
+
};
|
2196
|
+
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
2197
|
+
_options.defaultValues().then((values) => {
|
2198
|
+
reset(values, _options.resetOptions);
|
2199
|
+
_subjects.state.next({
|
2200
|
+
isLoading: false,
|
2201
|
+
});
|
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;
|
2227
|
+
},
|
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,
|
2273
|
+
};
|
2274
|
+
return {
|
2275
|
+
...methods,
|
2276
|
+
formControl: methods,
|
2277
|
+
};
|
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
|
+
}
|
2404
|
+
}
|
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),
|
2420
|
+
});
|
2166
2421
|
};
|
2167
|
-
const
|
2168
|
-
|
2169
|
-
const
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
...options,
|
2177
|
-
},
|
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),
|
2178
2431
|
});
|
2179
|
-
_names.mount.add(name);
|
2180
|
-
if (field) {
|
2181
|
-
_updateDisabledField({
|
2182
|
-
field,
|
2183
|
-
disabled: isBoolean(options.disabled)
|
2184
|
-
? options.disabled
|
2185
|
-
: _options.disabled,
|
2186
|
-
name,
|
2187
|
-
});
|
2188
|
-
}
|
2189
|
-
else {
|
2190
|
-
updateValidAndValue(name, true, options.value);
|
2191
|
-
}
|
2192
|
-
return {
|
2193
|
-
...(disabledIsDefined
|
2194
|
-
? { disabled: options.disabled || _options.disabled }
|
2195
|
-
: {}),
|
2196
|
-
...(_options.progressive
|
2197
|
-
? {
|
2198
|
-
required: !!options.required,
|
2199
|
-
min: getRuleValue(options.min),
|
2200
|
-
max: getRuleValue(options.max),
|
2201
|
-
minLength: getRuleValue(options.minLength),
|
2202
|
-
maxLength: getRuleValue(options.maxLength),
|
2203
|
-
pattern: getRuleValue(options.pattern),
|
2204
|
-
}
|
2205
|
-
: {}),
|
2206
|
-
name,
|
2207
|
-
onChange,
|
2208
|
-
onBlur: onChange,
|
2209
|
-
ref: (ref) => {
|
2210
|
-
if (ref) {
|
2211
|
-
register(name, options);
|
2212
|
-
field = get(_fields, name);
|
2213
|
-
const fieldRef = isUndefined(ref.value)
|
2214
|
-
? ref.querySelectorAll
|
2215
|
-
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
2216
|
-
: ref
|
2217
|
-
: ref;
|
2218
|
-
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
2219
|
-
const refs = field._f.refs || [];
|
2220
|
-
if (radioOrCheckbox
|
2221
|
-
? refs.find((option) => option === fieldRef)
|
2222
|
-
: fieldRef === field._f.ref) {
|
2223
|
-
return;
|
2224
|
-
}
|
2225
|
-
set(_fields, name, {
|
2226
|
-
_f: {
|
2227
|
-
...field._f,
|
2228
|
-
...(radioOrCheckbox
|
2229
|
-
? {
|
2230
|
-
refs: [
|
2231
|
-
...refs.filter(live),
|
2232
|
-
fieldRef,
|
2233
|
-
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
2234
|
-
],
|
2235
|
-
ref: { type: fieldRef.type, name },
|
2236
|
-
}
|
2237
|
-
: { ref: fieldRef }),
|
2238
|
-
},
|
2239
|
-
});
|
2240
|
-
updateValidAndValue(name, false, undefined, fieldRef);
|
2241
|
-
}
|
2242
|
-
else {
|
2243
|
-
field = get(_fields, name, {});
|
2244
|
-
if (field._f) {
|
2245
|
-
field._f.mount = false;
|
2246
|
-
}
|
2247
|
-
(_options.shouldUnregister || options.shouldUnregister) &&
|
2248
|
-
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
2249
|
-
_names.unMount.add(name);
|
2250
|
-
}
|
2251
|
-
},
|
2252
|
-
};
|
2253
|
-
};
|
2254
|
-
const _focusError = () => _options.shouldFocusError &&
|
2255
|
-
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
2256
|
-
const _disableForm = (disabled) => {
|
2257
|
-
if (isBoolean(disabled)) {
|
2258
|
-
_subjects.state.next({ disabled });
|
2259
|
-
iterateFieldsByAction(_fields, (ref, name) => {
|
2260
|
-
const currentField = get(_fields, name);
|
2261
|
-
if (currentField) {
|
2262
|
-
ref.disabled = currentField._f.disabled || disabled;
|
2263
|
-
if (Array.isArray(currentField._f.refs)) {
|
2264
|
-
currentField._f.refs.forEach((inputRef) => {
|
2265
|
-
inputRef.disabled = currentField._f.disabled || disabled;
|
2266
|
-
});
|
2267
|
-
}
|
2268
|
-
}
|
2269
|
-
}, 0, false);
|
2270
|
-
}
|
2271
2432
|
};
|
2272
|
-
const
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
set(fieldValues, name, undefined);
|
2282
|
-
}
|
2283
|
-
}
|
2284
|
-
_subjects.state.next({
|
2285
|
-
isSubmitting: true,
|
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,
|
2286
2442
|
});
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
errors: {},
|
2299
|
-
});
|
2300
|
-
try {
|
2301
|
-
await onValid(fieldValues, e);
|
2302
|
-
}
|
2303
|
-
catch (error) {
|
2304
|
-
onValidError = error;
|
2305
|
-
}
|
2306
|
-
}
|
2307
|
-
else {
|
2308
|
-
if (onInvalid) {
|
2309
|
-
await onInvalid({ ..._formState.errors }, e);
|
2310
|
-
}
|
2311
|
-
_focusError();
|
2312
|
-
setTimeout(_focusError);
|
2313
|
-
}
|
2314
|
-
_subjects.state.next({
|
2315
|
-
isSubmitted: true,
|
2316
|
-
isSubmitting: false,
|
2317
|
-
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
2318
|
-
submitCount: _formState.submitCount + 1,
|
2319
|
-
errors: _formState.errors,
|
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),
|
2320
2454
|
});
|
2321
|
-
if (onValidError) {
|
2322
|
-
throw onValidError;
|
2323
|
-
}
|
2324
2455
|
};
|
2325
|
-
const
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2329
|
-
|
2330
|
-
|
2331
|
-
|
2332
|
-
|
2333
|
-
|
2334
|
-
|
2335
|
-
unset(_formState.touchedFields, name);
|
2336
|
-
}
|
2337
|
-
if (!options.keepDirty) {
|
2338
|
-
unset(_formState.dirtyFields, name);
|
2339
|
-
_formState.isDirty = options.defaultValue
|
2340
|
-
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
2341
|
-
: _getDirty();
|
2342
|
-
}
|
2343
|
-
if (!options.keepError) {
|
2344
|
-
unset(_formState.errors, name);
|
2345
|
-
_proxyFormState.isValid && _updateValid();
|
2346
|
-
}
|
2347
|
-
_subjects.state.next({ ..._formState });
|
2348
|
-
}
|
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);
|
2349
2466
|
};
|
2350
|
-
const
|
2351
|
-
const
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
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);
|
2495
|
+
};
|
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
|
+
});
|
2369
2523
|
}
|
2370
2524
|
else {
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
if (form) {
|
2381
|
-
form.reset();
|
2382
|
-
break;
|
2383
|
-
}
|
2384
|
-
}
|
2385
|
-
}
|
2386
|
-
}
|
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
|
+
}));
|
2387
2534
|
}
|
2388
|
-
_fields = {};
|
2389
2535
|
}
|
2390
|
-
_formValues = _options.shouldUnregister
|
2391
|
-
? keepStateOptions.keepDefaultValues
|
2392
|
-
? cloneObject(_defaultValues)
|
2393
|
-
: {}
|
2394
|
-
: cloneObject(values);
|
2395
|
-
_subjects.array.next({
|
2396
|
-
values: { ...values },
|
2397
|
-
});
|
2398
|
-
_subjects.values.next({
|
2399
|
-
values: { ...values },
|
2400
|
-
});
|
2401
2536
|
}
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
array: new Set(),
|
2406
|
-
disabled: new Set(),
|
2407
|
-
watch: new Set(),
|
2408
|
-
watchAll: false,
|
2409
|
-
focus: '',
|
2410
|
-
};
|
2411
|
-
_state.mount =
|
2412
|
-
!_proxyFormState.isValid ||
|
2413
|
-
!!keepStateOptions.keepIsValid ||
|
2414
|
-
!!keepStateOptions.keepDirtyValues;
|
2415
|
-
_state.watch = !!_options.shouldUnregister;
|
2416
|
-
_subjects.state.next({
|
2417
|
-
submitCount: keepStateOptions.keepSubmitCount
|
2418
|
-
? _formState.submitCount
|
2419
|
-
: 0,
|
2420
|
-
isDirty: isEmptyResetValues
|
2421
|
-
? false
|
2422
|
-
: keepStateOptions.keepDirty
|
2423
|
-
? _formState.isDirty
|
2424
|
-
: !!(keepStateOptions.keepDefaultValues &&
|
2425
|
-
!deepEqual(formValues, _defaultValues)),
|
2426
|
-
isSubmitted: keepStateOptions.keepIsSubmitted
|
2427
|
-
? _formState.isSubmitted
|
2428
|
-
: false,
|
2429
|
-
dirtyFields: isEmptyResetValues
|
2430
|
-
? {}
|
2431
|
-
: keepStateOptions.keepDirtyValues
|
2432
|
-
? keepStateOptions.keepDefaultValues && _formValues
|
2433
|
-
? getDirtyFields(_defaultValues, _formValues)
|
2434
|
-
: _formState.dirtyFields
|
2435
|
-
: keepStateOptions.keepDefaultValues && formValues
|
2436
|
-
? getDirtyFields(_defaultValues, formValues)
|
2437
|
-
: keepStateOptions.keepDirty
|
2438
|
-
? _formState.dirtyFields
|
2439
|
-
: {},
|
2440
|
-
touchedFields: keepStateOptions.keepTouched
|
2441
|
-
? _formState.touchedFields
|
2442
|
-
: {},
|
2443
|
-
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
2444
|
-
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
2445
|
-
? _formState.isSubmitSuccessful
|
2446
|
-
: false,
|
2447
|
-
isSubmitting: false,
|
2537
|
+
control._subjects.state.next({
|
2538
|
+
name,
|
2539
|
+
values: { ...control._formValues },
|
2448
2540
|
});
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
|
2455
|
-
|
2456
|
-
|
2457
|
-
|
2458
|
-
? fieldReference.refs[0]
|
2459
|
-
: fieldReference.ref;
|
2460
|
-
if (fieldRef.focus) {
|
2461
|
-
fieldRef.focus();
|
2462
|
-
options.shouldSelect &&
|
2463
|
-
isFunction(fieldRef.select) &&
|
2464
|
-
fieldRef.select();
|
2465
|
-
}
|
2466
|
-
}
|
2467
|
-
};
|
2468
|
-
const _updateFormState = (updatedFormState) => {
|
2469
|
-
_formState = {
|
2470
|
-
..._formState,
|
2471
|
-
...updatedFormState,
|
2472
|
-
};
|
2473
|
-
};
|
2474
|
-
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
2475
|
-
_options.defaultValues().then((values) => {
|
2476
|
-
reset(values, _options.resetOptions);
|
2477
|
-
_subjects.state.next({
|
2478
|
-
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;
|
2479
2550
|
});
|
2480
|
-
|
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]);
|
2481
2562
|
return {
|
2482
|
-
|
2483
|
-
|
2484
|
-
|
2485
|
-
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
_updateDisabledField,
|
2495
|
-
_getFieldArray,
|
2496
|
-
_reset,
|
2497
|
-
_resetDefaultValues,
|
2498
|
-
_updateFormState,
|
2499
|
-
_disableForm,
|
2500
|
-
_subjects,
|
2501
|
-
_proxyFormState,
|
2502
|
-
_setErrors,
|
2503
|
-
get _fields() {
|
2504
|
-
return _fields;
|
2505
|
-
},
|
2506
|
-
get _formValues() {
|
2507
|
-
return _formValues;
|
2508
|
-
},
|
2509
|
-
get _state() {
|
2510
|
-
return _state;
|
2511
|
-
},
|
2512
|
-
set _state(value) {
|
2513
|
-
_state = value;
|
2514
|
-
},
|
2515
|
-
get _defaultValues() {
|
2516
|
-
return _defaultValues;
|
2517
|
-
},
|
2518
|
-
get _names() {
|
2519
|
-
return _names;
|
2520
|
-
},
|
2521
|
-
set _names(value) {
|
2522
|
-
_names = value;
|
2523
|
-
},
|
2524
|
-
get _formState() {
|
2525
|
-
return _formState;
|
2526
|
-
},
|
2527
|
-
set _formState(value) {
|
2528
|
-
_formState = value;
|
2529
|
-
},
|
2530
|
-
get _options() {
|
2531
|
-
return _options;
|
2532
|
-
},
|
2533
|
-
set _options(value) {
|
2534
|
-
_options = {
|
2535
|
-
..._options,
|
2536
|
-
...value,
|
2537
|
-
};
|
2538
|
-
},
|
2539
|
-
},
|
2540
|
-
trigger,
|
2541
|
-
register,
|
2542
|
-
handleSubmit,
|
2543
|
-
watch,
|
2544
|
-
setValue,
|
2545
|
-
getValues,
|
2546
|
-
reset,
|
2547
|
-
resetField,
|
2548
|
-
clearErrors,
|
2549
|
-
unregister,
|
2550
|
-
setError,
|
2551
|
-
setFocus,
|
2552
|
-
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]),
|
2553
2575
|
};
|
2554
2576
|
}
|
2555
2577
|
|
@@ -2605,20 +2627,17 @@ function useForm(props = {}) {
|
|
2605
2627
|
});
|
2606
2628
|
if (!_formControl.current) {
|
2607
2629
|
_formControl.current = {
|
2608
|
-
...createFormControl(props),
|
2630
|
+
...(props.control ? props.control : createFormControl(props)),
|
2609
2631
|
formState,
|
2610
2632
|
};
|
2611
2633
|
}
|
2612
2634
|
const control = _formControl.current.control;
|
2613
2635
|
control._options = props;
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2619
|
-
}
|
2620
|
-
},
|
2621
|
-
});
|
2636
|
+
React.useEffect(() => control._subscribe({
|
2637
|
+
formState: control._proxyFormState,
|
2638
|
+
callback: () => updateFormState({ ...control._formState }),
|
2639
|
+
reRenderRoot: true,
|
2640
|
+
}), [control]);
|
2622
2641
|
React.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
|
2623
2642
|
React.useEffect(() => {
|
2624
2643
|
if (control._proxyFormState.isDirty) {
|
@@ -2647,7 +2666,7 @@ function useForm(props = {}) {
|
|
2647
2666
|
}, [props.errors, control]);
|
2648
2667
|
React.useEffect(() => {
|
2649
2668
|
if (!control._state.mount) {
|
2650
|
-
control.
|
2669
|
+
control._setValid();
|
2651
2670
|
control._state.mount = true;
|
2652
2671
|
}
|
2653
2672
|
if (control._state.watch) {
|
@@ -2658,7 +2677,7 @@ function useForm(props = {}) {
|
|
2658
2677
|
});
|
2659
2678
|
React.useEffect(() => {
|
2660
2679
|
props.shouldUnregister &&
|
2661
|
-
control._subjects.
|
2680
|
+
control._subjects.state.next({
|
2662
2681
|
values: control._getWatch(),
|
2663
2682
|
});
|
2664
2683
|
}, [props.shouldUnregister, control]);
|
@@ -2666,5 +2685,5 @@ function useForm(props = {}) {
|
|
2666
2685
|
return _formControl.current;
|
2667
2686
|
}
|
2668
2687
|
|
2669
|
-
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 };
|
2670
2689
|
//# sourceMappingURL=index.esm.mjs.map
|