react-hook-form 7.81.0 → 7.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -9
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.mjs +2308 -2233
- 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.map +1 -1
- package/dist/logic/getDirtyFields.d.ts +3 -2
- package/dist/logic/getDirtyFields.d.ts.map +1 -1
- package/dist/logic/getEventValue.d.ts.map +1 -1
- package/dist/logic/getValueAndMessage.d.ts +1 -4
- package/dist/logic/getValueAndMessage.d.ts.map +1 -1
- package/dist/react-server.esm.mjs +111 -72
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/errors.d.ts +2 -2
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/form.d.ts +58 -57
- package/dist/types/form.d.ts.map +1 -1
- package/dist/types/path/common.d.ts +6 -0
- package/dist/types/path/common.d.ts.map +1 -1
- package/dist/types/path/eager.d.ts +15 -11
- package/dist/types/path/eager.d.ts.map +1 -1
- package/dist/types/utils.d.ts +1 -1
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/validator.d.ts +1 -1
- package/dist/types/validator.d.ts.map +1 -1
- package/dist/types/watch.d.ts +1 -1
- package/dist/types/watch.d.ts.map +1 -1
- package/dist/useFormContext.d.ts +1 -1
- package/dist/useFormContext.d.ts.map +1 -1
- package/dist/useFormState.d.ts +2 -2
- package/dist/useWatch.d.ts +14 -14
- package/package.json +7 -7
package/dist/index.esm.mjs
CHANGED
|
@@ -2,6 +2,8 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
var isCheckBoxInput = (element) => element.type === 'checkbox';
|
|
4
4
|
|
|
5
|
+
var isFileInput = (element) => element.type === 'file';
|
|
6
|
+
|
|
5
7
|
var isDateObject = (value) => value instanceof Date;
|
|
6
8
|
|
|
7
9
|
var isNullOrUndefined = (value) => value == null;
|
|
@@ -15,7 +17,9 @@ var isObject = (value) => !isNullOrUndefined(value) &&
|
|
|
15
17
|
var getEventValue = (event) => isObject(event) && event.target
|
|
16
18
|
? isCheckBoxInput(event.target)
|
|
17
19
|
? event.target.checked
|
|
18
|
-
: event.target
|
|
20
|
+
: isFileInput(event.target)
|
|
21
|
+
? event.target.files
|
|
22
|
+
: event.target.value
|
|
19
23
|
: event;
|
|
20
24
|
|
|
21
25
|
var isNameInFieldArray = (names, name) => name
|
|
@@ -167,12 +171,12 @@ const useIsomorphicLayoutEffect = isWeb
|
|
|
167
171
|
: React.useEffect;
|
|
168
172
|
|
|
169
173
|
/**
|
|
170
|
-
*
|
|
174
|
+
* Subscribes to each form state and isolates re-renders at the custom hook level. It has its own scope for form state subscriptions, so it will not affect other useFormState or useForm instances. Using this hook can reduce the re-render impact on large and complex form applications.
|
|
171
175
|
*
|
|
172
176
|
* @remarks
|
|
173
177
|
* [API](https://react-hook-form.com/docs/useformstate) • [Demo](https://codesandbox.io/s/useformstate-75xly)
|
|
174
178
|
*
|
|
175
|
-
* @param props -
|
|
179
|
+
* @param props - Include options to specify fields to subscribe to. {@link UseFormStateReturn}
|
|
176
180
|
*
|
|
177
181
|
* @example
|
|
178
182
|
* ```tsx
|
|
@@ -304,7 +308,7 @@ function deepEqual(object1, object2, visited = new WeakMap()) {
|
|
|
304
308
|
}
|
|
305
309
|
|
|
306
310
|
/**
|
|
307
|
-
* Custom hook to subscribe to field
|
|
311
|
+
* Custom hook to subscribe to field changes and isolate re-rendering at the component level.
|
|
308
312
|
*
|
|
309
313
|
* @remarks
|
|
310
314
|
*
|
|
@@ -314,7 +318,7 @@ function deepEqual(object1, object2, visited = new WeakMap()) {
|
|
|
314
318
|
* ```tsx
|
|
315
319
|
* const { control } = useForm();
|
|
316
320
|
* const values = useWatch({
|
|
317
|
-
* name: "fieldName"
|
|
321
|
+
* name: "fieldName",
|
|
318
322
|
* control,
|
|
319
323
|
* })
|
|
320
324
|
* ```
|
|
@@ -508,7 +512,7 @@ function useController(props) {
|
|
|
508
512
|
}), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
|
|
509
513
|
React.useEffect(() => {
|
|
510
514
|
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
|
511
|
-
control.register(name, {
|
|
515
|
+
_registerProps.current = control.register(name, {
|
|
512
516
|
..._props.current.rules,
|
|
513
517
|
...(isBoolean(_props.current.disabled)
|
|
514
518
|
? { disabled: _props.current.disabled }
|
|
@@ -602,308 +606,80 @@ function useController(props) {
|
|
|
602
606
|
*/
|
|
603
607
|
const Controller = (props) => props.render(useController(props));
|
|
604
608
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
if (isObjectType(obj[key]) &&
|
|
609
|
-
obj[key] !== null &&
|
|
610
|
-
!isDateObject(obj[key])) {
|
|
611
|
-
const nested = flatten(obj[key]);
|
|
612
|
-
for (const nestedKey of Object.keys(nested)) {
|
|
613
|
-
output[`${key}.${nestedKey}`] = nested[nestedKey];
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
else {
|
|
617
|
-
output[key] = obj[key];
|
|
618
|
-
}
|
|
609
|
+
var generateId = () => {
|
|
610
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
611
|
+
return crypto.randomUUID();
|
|
619
612
|
}
|
|
620
|
-
|
|
613
|
+
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
|
|
614
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
615
|
+
const r = ((Math.random() * 16 + d) % 16) | 0;
|
|
616
|
+
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
617
|
+
});
|
|
621
618
|
};
|
|
622
619
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
* );
|
|
647
|
-
* }
|
|
648
|
-
*
|
|
649
|
-
* function NestedInput() {
|
|
650
|
-
* const { register } = useFormContext(); // retrieve all hook methods
|
|
651
|
-
* return <input {...register("test")} />;
|
|
652
|
-
* }
|
|
653
|
-
* ```
|
|
654
|
-
*/
|
|
655
|
-
const useFormContext = () => React.useContext(HookFormContext);
|
|
656
|
-
/**
|
|
657
|
-
* A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
|
|
658
|
-
*
|
|
659
|
-
* @remarks
|
|
660
|
-
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
661
|
-
*
|
|
662
|
-
* @param props - all useForm methods
|
|
663
|
-
*
|
|
664
|
-
* @example
|
|
665
|
-
* ```tsx
|
|
666
|
-
* function App() {
|
|
667
|
-
* const methods = useForm();
|
|
668
|
-
* const onSubmit = data => console.log(data);
|
|
669
|
-
*
|
|
670
|
-
* return (
|
|
671
|
-
* <FormProvider {...methods} >
|
|
672
|
-
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
673
|
-
* <NestedInput />
|
|
674
|
-
* <input type="submit" />
|
|
675
|
-
* </form>
|
|
676
|
-
* </FormProvider>
|
|
677
|
-
* );
|
|
678
|
-
* }
|
|
679
|
-
*
|
|
680
|
-
* function NestedInput() {
|
|
681
|
-
* const { register } = useFormContext(); // retrieve all hook methods
|
|
682
|
-
* return <input {...register("test")} />;
|
|
683
|
-
* }
|
|
684
|
-
* ```
|
|
685
|
-
*/
|
|
686
|
-
const FormProvider = ({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
|
|
687
|
-
const memoizedValue = React.useMemo(() => ({
|
|
688
|
-
watch,
|
|
689
|
-
getValues,
|
|
690
|
-
getFieldState,
|
|
691
|
-
setError,
|
|
692
|
-
clearErrors,
|
|
693
|
-
setValue,
|
|
694
|
-
setValues,
|
|
695
|
-
trigger,
|
|
696
|
-
formState,
|
|
697
|
-
resetField,
|
|
698
|
-
reset,
|
|
699
|
-
handleSubmit,
|
|
700
|
-
unregister,
|
|
701
|
-
control,
|
|
702
|
-
register,
|
|
703
|
-
setFocus,
|
|
704
|
-
subscribe,
|
|
705
|
-
}), [
|
|
706
|
-
clearErrors,
|
|
707
|
-
control,
|
|
708
|
-
formState,
|
|
709
|
-
getFieldState,
|
|
710
|
-
getValues,
|
|
711
|
-
handleSubmit,
|
|
712
|
-
register,
|
|
713
|
-
reset,
|
|
714
|
-
resetField,
|
|
715
|
-
setError,
|
|
716
|
-
setFocus,
|
|
717
|
-
setValue,
|
|
718
|
-
setValues,
|
|
719
|
-
subscribe,
|
|
720
|
-
trigger,
|
|
721
|
-
unregister,
|
|
722
|
-
watch,
|
|
723
|
-
]);
|
|
724
|
-
return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
|
|
725
|
-
React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
|
|
620
|
+
var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
|
|
621
|
+
? options.focusName ||
|
|
622
|
+
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
|
623
|
+
: '';
|
|
624
|
+
|
|
625
|
+
var getValidationModes = (mode) => ({
|
|
626
|
+
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
|
|
627
|
+
isOnBlur: mode === VALIDATION_MODE.onBlur,
|
|
628
|
+
isOnChange: mode === VALIDATION_MODE.onChange,
|
|
629
|
+
isOnAll: mode === VALIDATION_MODE.all,
|
|
630
|
+
isOnTouch: mode === VALIDATION_MODE.onTouched,
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
var isWatched = (name, _names, isBlurEvent) => {
|
|
634
|
+
if (isBlurEvent)
|
|
635
|
+
return false;
|
|
636
|
+
if (_names.watchAll || _names.watch.has(name))
|
|
637
|
+
return true;
|
|
638
|
+
for (const watchName of _names.watch) {
|
|
639
|
+
if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
642
|
+
return false;
|
|
726
643
|
};
|
|
727
644
|
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
* <input {...register("name")} />
|
|
744
|
-
* <p>{errors?.root?.server && 'Server error'}</p>
|
|
745
|
-
* <button>Submit</button>
|
|
746
|
-
* </Form>
|
|
747
|
-
* );
|
|
748
|
-
* }
|
|
749
|
-
* ```
|
|
750
|
-
*/
|
|
751
|
-
function Form(props) {
|
|
752
|
-
const methods = useFormContext();
|
|
753
|
-
const [mounted, setMounted] = React.useState(false);
|
|
754
|
-
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
|
|
755
|
-
const submit = React.useCallback(async (event) => {
|
|
756
|
-
let hasError = false;
|
|
757
|
-
let type = '';
|
|
758
|
-
await control.handleSubmit(async (data) => {
|
|
759
|
-
const formData = new FormData();
|
|
760
|
-
let formDataJson = '';
|
|
761
|
-
try {
|
|
762
|
-
formDataJson = JSON.stringify(data);
|
|
763
|
-
}
|
|
764
|
-
catch (_a) { }
|
|
765
|
-
const flattenFormValues = flatten(data);
|
|
766
|
-
for (const key in flattenFormValues) {
|
|
767
|
-
formData.append(key, flattenFormValues[key]);
|
|
768
|
-
}
|
|
769
|
-
if (onSubmit) {
|
|
770
|
-
await onSubmit({
|
|
771
|
-
data,
|
|
772
|
-
event,
|
|
773
|
-
method,
|
|
774
|
-
formData,
|
|
775
|
-
formDataJson,
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
if (action) {
|
|
779
|
-
try {
|
|
780
|
-
const shouldStringifySubmissionData = [
|
|
781
|
-
headers && headers['Content-Type'],
|
|
782
|
-
encType,
|
|
783
|
-
].some((value) => value && value.includes('json'));
|
|
784
|
-
const response = await fetch(String(action), {
|
|
785
|
-
method,
|
|
786
|
-
headers: {
|
|
787
|
-
...headers,
|
|
788
|
-
...(encType && encType !== 'multipart/form-data'
|
|
789
|
-
? { 'Content-Type': encType }
|
|
790
|
-
: {}),
|
|
791
|
-
},
|
|
792
|
-
body: shouldStringifySubmissionData ? formDataJson : formData,
|
|
793
|
-
});
|
|
794
|
-
if (response &&
|
|
795
|
-
(validateStatus
|
|
796
|
-
? !validateStatus(response.status)
|
|
797
|
-
: response.status < 200 || response.status >= 300)) {
|
|
798
|
-
hasError = true;
|
|
799
|
-
onError && onError({ response });
|
|
800
|
-
type = String(response.status);
|
|
801
|
-
}
|
|
802
|
-
else {
|
|
803
|
-
onSuccess && onSuccess({ response });
|
|
645
|
+
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
|
646
|
+
for (const key of fieldsNames || Object.keys(fields)) {
|
|
647
|
+
const field = get(fields, key);
|
|
648
|
+
if (field) {
|
|
649
|
+
const { _f, ...currentField } = field;
|
|
650
|
+
if (_f) {
|
|
651
|
+
if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
|
|
655
|
+
return true;
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
if (iterateFieldsByAction(currentField, action)) {
|
|
659
|
+
break;
|
|
804
660
|
}
|
|
805
661
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
662
|
+
}
|
|
663
|
+
else if (isObject(currentField)) {
|
|
664
|
+
if (iterateFieldsByAction(currentField, action)) {
|
|
665
|
+
break;
|
|
809
666
|
}
|
|
810
667
|
}
|
|
811
|
-
})(event);
|
|
812
|
-
if (hasError && control) {
|
|
813
|
-
control._subjects.state.next({
|
|
814
|
-
isSubmitSuccessful: false,
|
|
815
|
-
});
|
|
816
|
-
control.setError('root.server', {
|
|
817
|
-
type,
|
|
818
|
-
});
|
|
819
668
|
}
|
|
820
|
-
}, [
|
|
821
|
-
control,
|
|
822
|
-
onSubmit,
|
|
823
|
-
method,
|
|
824
|
-
action,
|
|
825
|
-
headers,
|
|
826
|
-
encType,
|
|
827
|
-
validateStatus,
|
|
828
|
-
onError,
|
|
829
|
-
onSuccess,
|
|
830
|
-
]);
|
|
831
|
-
React.useEffect(() => {
|
|
832
|
-
setMounted(true);
|
|
833
|
-
}, []);
|
|
834
|
-
return render ? (React.createElement(React.Fragment, null, render({
|
|
835
|
-
submit,
|
|
836
|
-
}))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
|
|
840
|
-
|
|
841
|
-
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
|
842
|
-
? {
|
|
843
|
-
...errors[name],
|
|
844
|
-
types: {
|
|
845
|
-
...(errors[name] && errors[name].types ? errors[name].types : {}),
|
|
846
|
-
[type]: message || true,
|
|
847
|
-
},
|
|
848
669
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
|
|
852
|
-
|
|
853
|
-
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
|
854
|
-
|
|
855
|
-
var createSubject = () => {
|
|
856
|
-
let _observers = [];
|
|
857
|
-
const next = (value) => {
|
|
858
|
-
for (const observer of _observers) {
|
|
859
|
-
observer.next && observer.next(value);
|
|
860
|
-
}
|
|
861
|
-
};
|
|
862
|
-
const subscribe = (observer) => {
|
|
863
|
-
_observers.push(observer);
|
|
864
|
-
return {
|
|
865
|
-
unsubscribe: () => {
|
|
866
|
-
_observers = _observers.filter((o) => o !== observer);
|
|
867
|
-
},
|
|
868
|
-
};
|
|
869
|
-
};
|
|
870
|
-
const unsubscribe = () => {
|
|
871
|
-
_observers = [];
|
|
872
|
-
};
|
|
873
|
-
return {
|
|
874
|
-
get observers() {
|
|
875
|
-
return _observers;
|
|
876
|
-
},
|
|
877
|
-
next,
|
|
878
|
-
subscribe,
|
|
879
|
-
unsubscribe,
|
|
880
|
-
};
|
|
670
|
+
return;
|
|
881
671
|
};
|
|
882
672
|
|
|
883
|
-
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
const nestedFieldsState = extractFormValues(fieldState, fieldValue);
|
|
891
|
-
if (isObject(nestedFieldsState)) {
|
|
892
|
-
values[key] = nestedFieldsState;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
else if (fieldsState[key]) {
|
|
896
|
-
values[key] = fieldValue;
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
return values;
|
|
901
|
-
}
|
|
673
|
+
var updateFieldArrayRootError = (errors, error, name) => {
|
|
674
|
+
const existingErrors = get(errors, name);
|
|
675
|
+
const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
|
|
676
|
+
set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
|
|
677
|
+
set(errors, name, fieldArrayErrors);
|
|
678
|
+
return errors;
|
|
679
|
+
};
|
|
902
680
|
|
|
903
681
|
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
|
904
682
|
|
|
905
|
-
var isFileInput = (element) => element.type === 'file';
|
|
906
|
-
|
|
907
683
|
var isHTMLElement = (value) => {
|
|
908
684
|
if (!isWeb) {
|
|
909
685
|
return false;
|
|
@@ -913,131 +689,19 @@ var isHTMLElement = (value) => {
|
|
|
913
689
|
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
|
|
914
690
|
};
|
|
915
691
|
|
|
916
|
-
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
|
917
|
-
|
|
918
692
|
var isRadioInput = (element) => element.type === 'radio';
|
|
919
693
|
|
|
920
|
-
var
|
|
921
|
-
|
|
922
|
-
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
|
923
|
-
|
|
924
|
-
function baseGet(object, updatePath) {
|
|
925
|
-
const length = updatePath.slice(0, -1).length;
|
|
926
|
-
let index = 0;
|
|
927
|
-
while (index < length) {
|
|
928
|
-
if (isNullOrUndefined(object)) {
|
|
929
|
-
object = undefined;
|
|
930
|
-
break;
|
|
931
|
-
}
|
|
932
|
-
object = object[updatePath[index]];
|
|
933
|
-
index++;
|
|
934
|
-
}
|
|
935
|
-
return object;
|
|
936
|
-
}
|
|
937
|
-
function isEmptyArray(obj) {
|
|
938
|
-
for (const key in obj) {
|
|
939
|
-
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
|
940
|
-
return false;
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
return true;
|
|
944
|
-
}
|
|
945
|
-
function unset(object, path) {
|
|
946
|
-
if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
|
|
947
|
-
delete object[path];
|
|
948
|
-
return object;
|
|
949
|
-
}
|
|
950
|
-
const paths = Array.isArray(path)
|
|
951
|
-
? path
|
|
952
|
-
: isKey(path)
|
|
953
|
-
? [path]
|
|
954
|
-
: stringToPath(path);
|
|
955
|
-
if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
|
|
956
|
-
return object;
|
|
957
|
-
}
|
|
958
|
-
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
|
959
|
-
const index = paths.length - 1;
|
|
960
|
-
const key = paths[index];
|
|
961
|
-
if (childObject) {
|
|
962
|
-
delete childObject[key];
|
|
963
|
-
}
|
|
964
|
-
if (index !== 0 &&
|
|
965
|
-
((isObject(childObject) && isEmptyObject(childObject)) ||
|
|
966
|
-
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
|
967
|
-
unset(object, paths.slice(0, -1));
|
|
968
|
-
}
|
|
969
|
-
return object;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
var objectHasFunction = (data) => {
|
|
973
|
-
for (const key in data) {
|
|
974
|
-
if (isFunction(data[key])) {
|
|
975
|
-
return true;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
return false;
|
|
979
|
-
};
|
|
694
|
+
var isRegex = (value) => value instanceof RegExp;
|
|
980
695
|
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
fields[key] = Array.isArray(value) ? [] : {};
|
|
989
|
-
markFieldsDirty(value, fields[key]);
|
|
990
|
-
}
|
|
991
|
-
else if (!isUndefined(value)) {
|
|
992
|
-
fields[key] = true;
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
return fields;
|
|
996
|
-
}
|
|
997
|
-
function pruneDirtyFields(value) {
|
|
998
|
-
if (value === false) {
|
|
999
|
-
return undefined;
|
|
1000
|
-
}
|
|
1001
|
-
if (value === true) {
|
|
1002
|
-
return true;
|
|
1003
|
-
}
|
|
1004
|
-
if (Array.isArray(value)) {
|
|
1005
|
-
const result = value.map((value) => pruneDirtyFields(value));
|
|
1006
|
-
return (result.some((value) => value !== undefined) ? result : undefined);
|
|
1007
|
-
}
|
|
1008
|
-
if (isObject(value)) {
|
|
1009
|
-
const result = {};
|
|
1010
|
-
for (const key in value) {
|
|
1011
|
-
const pruned = pruneDirtyFields(value[key]);
|
|
1012
|
-
if (!isUndefined(pruned)) {
|
|
1013
|
-
result[key] = pruned;
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
return (Object.keys(result).length ? result : undefined);
|
|
1017
|
-
}
|
|
1018
|
-
return undefined;
|
|
1019
|
-
}
|
|
1020
|
-
function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
|
|
1021
|
-
if (!dirtyFieldsFromValues) {
|
|
1022
|
-
dirtyFieldsFromValues = markFieldsDirty(formValues);
|
|
1023
|
-
}
|
|
1024
|
-
for (const key in data) {
|
|
1025
|
-
const value = data[key];
|
|
1026
|
-
if (isTraversable(value)) {
|
|
1027
|
-
if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
|
|
1028
|
-
dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {});
|
|
1029
|
-
}
|
|
1030
|
-
else {
|
|
1031
|
-
getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
else {
|
|
1035
|
-
const formValue = formValues[key];
|
|
1036
|
-
dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
|
|
1037
|
-
}
|
|
696
|
+
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
|
697
|
+
? {
|
|
698
|
+
...errors[name],
|
|
699
|
+
types: {
|
|
700
|
+
...(errors[name] && errors[name].types ? errors[name].types : {}),
|
|
701
|
+
[type]: message || true,
|
|
702
|
+
},
|
|
1038
703
|
}
|
|
1039
|
-
|
|
1040
|
-
}
|
|
704
|
+
: {};
|
|
1041
705
|
|
|
1042
706
|
const defaultResult = {
|
|
1043
707
|
value: false,
|
|
@@ -1064,20 +728,6 @@ var getCheckboxValue = (options) => {
|
|
|
1064
728
|
return defaultResult;
|
|
1065
729
|
};
|
|
1066
730
|
|
|
1067
|
-
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
|
1068
|
-
? value
|
|
1069
|
-
: valueAsNumber
|
|
1070
|
-
? value === ''
|
|
1071
|
-
? NaN
|
|
1072
|
-
: value
|
|
1073
|
-
? +value
|
|
1074
|
-
: value
|
|
1075
|
-
: valueAsDate && isString(value)
|
|
1076
|
-
? new Date(value)
|
|
1077
|
-
: setValueAs
|
|
1078
|
-
? setValueAs(value)
|
|
1079
|
-
: value;
|
|
1080
|
-
|
|
1081
731
|
const defaultReturn = {
|
|
1082
732
|
isValid: false,
|
|
1083
733
|
value: null,
|
|
@@ -1091,221 +741,23 @@ var getRadioValue = (options) => Array.isArray(options)
|
|
|
1091
741
|
: previous, defaultReturn)
|
|
1092
742
|
: defaultReturn;
|
|
1093
743
|
|
|
1094
|
-
function
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
return [...ref.selectedOptions].map(({ value }) => value);
|
|
1104
|
-
}
|
|
1105
|
-
if (isCheckBoxInput(ref)) {
|
|
1106
|
-
return getCheckboxValue(_f.refs).value;
|
|
744
|
+
function getValidateError(result, ref, type = 'validate') {
|
|
745
|
+
if (isString(result) ||
|
|
746
|
+
(Array.isArray(result) && result.every(isString)) ||
|
|
747
|
+
(isBoolean(result) && !result)) {
|
|
748
|
+
return {
|
|
749
|
+
type,
|
|
750
|
+
message: isString(result) ? result : '',
|
|
751
|
+
ref,
|
|
752
|
+
};
|
|
1107
753
|
}
|
|
1108
|
-
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
|
1109
754
|
}
|
|
1110
755
|
|
|
1111
|
-
var
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
}
|
|
1117
|
-
return {
|
|
1118
|
-
criteriaMode,
|
|
1119
|
-
names: [...fieldsNames],
|
|
1120
|
-
fields,
|
|
1121
|
-
shouldUseNativeValidation,
|
|
1122
|
-
};
|
|
1123
|
-
};
|
|
1124
|
-
|
|
1125
|
-
var isRegex = (value) => value instanceof RegExp;
|
|
1126
|
-
|
|
1127
|
-
var getRuleValue = (rule) => isUndefined(rule)
|
|
1128
|
-
? rule
|
|
1129
|
-
: isRegex(rule)
|
|
1130
|
-
? rule.source
|
|
1131
|
-
: isObject(rule)
|
|
1132
|
-
? isRegex(rule.value)
|
|
1133
|
-
? rule.value.source
|
|
1134
|
-
: rule.value
|
|
1135
|
-
: rule;
|
|
1136
|
-
|
|
1137
|
-
var getValidationModes = (mode) => ({
|
|
1138
|
-
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
|
|
1139
|
-
isOnBlur: mode === VALIDATION_MODE.onBlur,
|
|
1140
|
-
isOnChange: mode === VALIDATION_MODE.onChange,
|
|
1141
|
-
isOnAll: mode === VALIDATION_MODE.all,
|
|
1142
|
-
isOnTouch: mode === VALIDATION_MODE.onTouched,
|
|
1143
|
-
});
|
|
1144
|
-
|
|
1145
|
-
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
1146
|
-
var hasPromiseValidation = (fieldReference) => {
|
|
1147
|
-
if (!fieldReference || !fieldReference.validate)
|
|
1148
|
-
return false;
|
|
1149
|
-
if (isFunction(fieldReference.validate)) {
|
|
1150
|
-
return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
|
|
1151
|
-
}
|
|
1152
|
-
if (isObject(fieldReference.validate)) {
|
|
1153
|
-
for (const key in fieldReference.validate) {
|
|
1154
|
-
if (fieldReference.validate[key].constructor
|
|
1155
|
-
.name === ASYNC_FUNCTION) {
|
|
1156
|
-
return true;
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
return false;
|
|
1161
|
-
};
|
|
1162
|
-
|
|
1163
|
-
var hasValidation = (options) => options.mount &&
|
|
1164
|
-
(options.required ||
|
|
1165
|
-
options.min ||
|
|
1166
|
-
options.max ||
|
|
1167
|
-
options.maxLength ||
|
|
1168
|
-
options.minLength ||
|
|
1169
|
-
options.pattern ||
|
|
1170
|
-
options.validate);
|
|
1171
|
-
|
|
1172
|
-
var isWatched = (name, _names, isBlurEvent) => {
|
|
1173
|
-
if (isBlurEvent)
|
|
1174
|
-
return false;
|
|
1175
|
-
if (_names.watchAll || _names.watch.has(name))
|
|
1176
|
-
return true;
|
|
1177
|
-
for (const watchName of _names.watch) {
|
|
1178
|
-
if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
|
|
1179
|
-
return true;
|
|
1180
|
-
}
|
|
1181
|
-
return false;
|
|
1182
|
-
};
|
|
1183
|
-
|
|
1184
|
-
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
|
1185
|
-
for (const key of fieldsNames || Object.keys(fields)) {
|
|
1186
|
-
const field = get(fields, key);
|
|
1187
|
-
if (field) {
|
|
1188
|
-
const { _f, ...currentField } = field;
|
|
1189
|
-
if (_f) {
|
|
1190
|
-
if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
|
|
1191
|
-
return true;
|
|
1192
|
-
}
|
|
1193
|
-
else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
|
|
1194
|
-
return true;
|
|
1195
|
-
}
|
|
1196
|
-
else {
|
|
1197
|
-
if (iterateFieldsByAction(currentField, action)) {
|
|
1198
|
-
break;
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
else if (isObject(currentField)) {
|
|
1203
|
-
if (iterateFieldsByAction(currentField, action)) {
|
|
1204
|
-
break;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
return;
|
|
1210
|
-
};
|
|
1211
|
-
|
|
1212
|
-
function schemaErrorLookup(errors, _fields, name) {
|
|
1213
|
-
const error = get(errors, name);
|
|
1214
|
-
if (error || isKey(name)) {
|
|
1215
|
-
return {
|
|
1216
|
-
error,
|
|
1217
|
-
name,
|
|
1218
|
-
};
|
|
1219
|
-
}
|
|
1220
|
-
const names = name.split('.');
|
|
1221
|
-
while (names.length) {
|
|
1222
|
-
const fieldName = names.join('.');
|
|
1223
|
-
const field = get(_fields, fieldName);
|
|
1224
|
-
const foundError = get(errors, fieldName);
|
|
1225
|
-
if (field && !Array.isArray(field) && name !== fieldName) {
|
|
1226
|
-
return { name };
|
|
1227
|
-
}
|
|
1228
|
-
if (foundError && foundError.type) {
|
|
1229
|
-
return {
|
|
1230
|
-
name: fieldName,
|
|
1231
|
-
error: foundError,
|
|
1232
|
-
};
|
|
1233
|
-
}
|
|
1234
|
-
if (foundError && foundError.root && foundError.root.type) {
|
|
1235
|
-
return {
|
|
1236
|
-
name: `${fieldName}.root`,
|
|
1237
|
-
error: foundError.root,
|
|
1238
|
-
};
|
|
1239
|
-
}
|
|
1240
|
-
names.pop();
|
|
1241
|
-
}
|
|
1242
|
-
return {
|
|
1243
|
-
name,
|
|
1244
|
-
};
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
1248
|
-
updateFormState(formStateData);
|
|
1249
|
-
const { name, ...formState } = formStateData;
|
|
1250
|
-
const keys = Object.keys(formState);
|
|
1251
|
-
return (!keys.length ||
|
|
1252
|
-
(isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
|
|
1253
|
-
keys.find((key) => _proxyFormState[key] ===
|
|
1254
|
-
(!isRoot || VALIDATION_MODE.all)));
|
|
1255
|
-
};
|
|
1256
|
-
|
|
1257
|
-
var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
|
1258
|
-
!signalName ||
|
|
1259
|
-
name === signalName ||
|
|
1260
|
-
convertToArrayPayload(name).some((currentName) => currentName &&
|
|
1261
|
-
(exact
|
|
1262
|
-
? currentName === signalName || currentName.startsWith(signalName + '.')
|
|
1263
|
-
: currentName.startsWith(signalName) ||
|
|
1264
|
-
signalName.startsWith(currentName)));
|
|
1265
|
-
|
|
1266
|
-
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
|
|
1267
|
-
if (mode.isOnAll) {
|
|
1268
|
-
return false;
|
|
1269
|
-
}
|
|
1270
|
-
else if (!isSubmitted && mode.isOnTouch) {
|
|
1271
|
-
return !(isTouched || isBlurEvent);
|
|
1272
|
-
}
|
|
1273
|
-
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
|
|
1274
|
-
return !isBlurEvent;
|
|
1275
|
-
}
|
|
1276
|
-
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
|
|
1277
|
-
return isBlurEvent;
|
|
1278
|
-
}
|
|
1279
|
-
return true;
|
|
1280
|
-
};
|
|
1281
|
-
|
|
1282
|
-
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
|
1283
|
-
|
|
1284
|
-
var updateFieldArrayRootError = (errors, error, name) => {
|
|
1285
|
-
const existingErrors = get(errors, name);
|
|
1286
|
-
const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
|
|
1287
|
-
set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
|
|
1288
|
-
set(errors, name, fieldArrayErrors);
|
|
1289
|
-
return errors;
|
|
1290
|
-
};
|
|
1291
|
-
|
|
1292
|
-
function getValidateError(result, ref, type = 'validate') {
|
|
1293
|
-
if (isString(result) ||
|
|
1294
|
-
(Array.isArray(result) && result.every(isString)) ||
|
|
1295
|
-
(isBoolean(result) && !result)) {
|
|
1296
|
-
return {
|
|
1297
|
-
type,
|
|
1298
|
-
message: isString(result) ? result : '',
|
|
1299
|
-
ref,
|
|
1300
|
-
};
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
|
|
1305
|
-
? validationData
|
|
1306
|
-
: {
|
|
1307
|
-
value: validationData,
|
|
1308
|
-
message: '',
|
|
756
|
+
var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
|
|
757
|
+
? validationData
|
|
758
|
+
: {
|
|
759
|
+
value: validationData,
|
|
760
|
+
message: '',
|
|
1309
761
|
};
|
|
1310
762
|
|
|
1311
763
|
var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
|
|
@@ -1493,1760 +945,2383 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
|
|
|
1493
945
|
return error;
|
|
1494
946
|
};
|
|
1495
947
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
948
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
|
949
|
+
|
|
950
|
+
var appendAt = (data, value) => [
|
|
951
|
+
...data,
|
|
952
|
+
...convertToArrayPayload(value),
|
|
953
|
+
];
|
|
954
|
+
|
|
955
|
+
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
|
|
956
|
+
|
|
957
|
+
function insert(data, index, value) {
|
|
958
|
+
return [
|
|
959
|
+
...data.slice(0, index),
|
|
960
|
+
...convertToArrayPayload(value),
|
|
961
|
+
...data.slice(index),
|
|
962
|
+
];
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
var moveArrayAt = (data, from, to) => {
|
|
966
|
+
if (!Array.isArray(data)) {
|
|
967
|
+
return [];
|
|
968
|
+
}
|
|
969
|
+
if (isUndefined(data[to])) {
|
|
970
|
+
data[to] = undefined;
|
|
971
|
+
}
|
|
972
|
+
data.splice(to, 0, data.splice(from, 1)[0]);
|
|
973
|
+
return data;
|
|
1500
974
|
};
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
975
|
+
|
|
976
|
+
var prependAt = (data, value) => [
|
|
977
|
+
...convertToArrayPayload(value),
|
|
978
|
+
...convertToArrayPayload(data),
|
|
979
|
+
];
|
|
980
|
+
|
|
981
|
+
var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
|
|
982
|
+
|
|
983
|
+
function removeAtIndexes(data, indexes) {
|
|
984
|
+
let i = 0;
|
|
985
|
+
const temp = [...data];
|
|
986
|
+
for (const index of indexes) {
|
|
987
|
+
temp.splice(index - i, 1);
|
|
988
|
+
i++;
|
|
989
|
+
}
|
|
990
|
+
return compact(temp).length ? temp : [];
|
|
991
|
+
}
|
|
992
|
+
var removeArrayAt = (data, index) => isUndefined(index)
|
|
993
|
+
? []
|
|
994
|
+
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
|
995
|
+
|
|
996
|
+
var swapArrayAt = (data, indexA, indexB) => {
|
|
997
|
+
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
|
1514
998
|
};
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
999
|
+
|
|
1000
|
+
function baseGet(object, updatePath) {
|
|
1001
|
+
const length = updatePath.slice(0, -1).length;
|
|
1002
|
+
let index = 0;
|
|
1003
|
+
while (index < length) {
|
|
1004
|
+
if (isNullOrUndefined(object)) {
|
|
1005
|
+
object = undefined;
|
|
1006
|
+
break;
|
|
1007
|
+
}
|
|
1008
|
+
object = object[updatePath[index]];
|
|
1009
|
+
index++;
|
|
1010
|
+
}
|
|
1011
|
+
return object;
|
|
1012
|
+
}
|
|
1013
|
+
function isEmptyArray(obj) {
|
|
1014
|
+
for (const key in obj) {
|
|
1015
|
+
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
|
1016
|
+
return false;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
return true;
|
|
1020
|
+
}
|
|
1021
|
+
function unset(object, path) {
|
|
1022
|
+
if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
|
|
1023
|
+
delete object[path];
|
|
1024
|
+
return object;
|
|
1025
|
+
}
|
|
1026
|
+
const paths = Array.isArray(path)
|
|
1027
|
+
? path
|
|
1028
|
+
: isKey(path)
|
|
1029
|
+
? [path]
|
|
1030
|
+
: stringToPath(path);
|
|
1031
|
+
if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
|
|
1032
|
+
return object;
|
|
1033
|
+
}
|
|
1034
|
+
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
|
1035
|
+
const index = paths.length - 1;
|
|
1036
|
+
const key = paths[index];
|
|
1037
|
+
if (childObject) {
|
|
1038
|
+
delete childObject[key];
|
|
1039
|
+
}
|
|
1040
|
+
if (index !== 0 &&
|
|
1041
|
+
((isObject(childObject) && isEmptyObject(childObject)) ||
|
|
1042
|
+
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
|
1043
|
+
unset(object, paths.slice(0, -1));
|
|
1044
|
+
}
|
|
1045
|
+
return object;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
var updateAt = (fieldValues, index, value) => {
|
|
1049
|
+
fieldValues[index] = value;
|
|
1050
|
+
return fieldValues;
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* 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)
|
|
1055
|
+
*
|
|
1056
|
+
* @remarks
|
|
1057
|
+
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
|
1058
|
+
*
|
|
1059
|
+
* @param props - useFieldArray props
|
|
1060
|
+
*
|
|
1061
|
+
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
|
1062
|
+
*
|
|
1063
|
+
* @example
|
|
1064
|
+
* ```tsx
|
|
1065
|
+
* function App() {
|
|
1066
|
+
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
|
1067
|
+
* defaultValues: {
|
|
1068
|
+
* test: []
|
|
1069
|
+
* }
|
|
1070
|
+
* });
|
|
1071
|
+
* const { fields, append } = useFieldArray({
|
|
1072
|
+
* control,
|
|
1073
|
+
* name: "test"
|
|
1074
|
+
* });
|
|
1075
|
+
*
|
|
1076
|
+
* return (
|
|
1077
|
+
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
|
1078
|
+
* {fields.map((item, index) => (
|
|
1079
|
+
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
|
1080
|
+
* ))}
|
|
1081
|
+
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
|
1082
|
+
* append
|
|
1083
|
+
* </button>
|
|
1084
|
+
* <input type="submit" />
|
|
1085
|
+
* </form>
|
|
1086
|
+
* );
|
|
1087
|
+
* }
|
|
1088
|
+
* ```
|
|
1089
|
+
*/
|
|
1090
|
+
function useFieldArray(props) {
|
|
1091
|
+
const formControl = useFormControlContext();
|
|
1092
|
+
const { control = formControl, name, keyName = 'id', disabled, shouldUnregister, rules, } = props;
|
|
1093
|
+
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
|
1094
|
+
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
|
1095
|
+
const _actioned = React.useRef(false);
|
|
1096
|
+
if (!disabled) {
|
|
1097
|
+
control._names.array.add(name);
|
|
1098
|
+
}
|
|
1099
|
+
React.useMemo(() => !disabled &&
|
|
1100
|
+
rules &&
|
|
1101
|
+
fields.length >= 0 &&
|
|
1102
|
+
control.register(name, rules), [control, name, fields.length, rules, disabled]);
|
|
1103
|
+
useIsomorphicLayoutEffect(() => {
|
|
1104
|
+
if (disabled) {
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
return control._subjects.array.subscribe({
|
|
1108
|
+
next: ({ values, name: fieldArrayName, }) => {
|
|
1109
|
+
if (fieldArrayName === name || !fieldArrayName) {
|
|
1110
|
+
const fieldValues = get(values, name);
|
|
1111
|
+
if (Array.isArray(fieldValues)) {
|
|
1112
|
+
setFields(fieldValues);
|
|
1113
|
+
ids.current = fieldValues.map(generateId);
|
|
1114
|
+
}
|
|
1115
|
+
else if (!fieldArrayName) {
|
|
1116
|
+
setFields([]);
|
|
1117
|
+
ids.current = [];
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
},
|
|
1121
|
+
}).unsubscribe;
|
|
1122
|
+
}, [control, name, disabled]);
|
|
1123
|
+
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
|
1124
|
+
_actioned.current = true;
|
|
1125
|
+
control._setFieldArray(name, updatedFieldArrayValues);
|
|
1126
|
+
}, [control, name]);
|
|
1127
|
+
const append = (value, options) => {
|
|
1128
|
+
if (disabled) {
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
const appendValue = convertToArrayPayload(cloneObject(value));
|
|
1132
|
+
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
|
|
1133
|
+
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
|
|
1134
|
+
ids.current = appendAt(ids.current, appendValue.map(generateId));
|
|
1135
|
+
updateValues(updatedFieldArrayValues);
|
|
1136
|
+
setFields(updatedFieldArrayValues);
|
|
1137
|
+
control._setFieldArray(name, updatedFieldArrayValues, appendAt, {
|
|
1138
|
+
argA: fillEmptyArray(value),
|
|
1139
|
+
});
|
|
1546
1140
|
};
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1141
|
+
const prepend = (value, options) => {
|
|
1142
|
+
if (disabled) {
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
const prependValue = convertToArrayPayload(cloneObject(value));
|
|
1146
|
+
const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
|
|
1147
|
+
control._names.focus = getFocusFieldName(name, 0, options);
|
|
1148
|
+
ids.current = prependAt(ids.current, prependValue.map(generateId));
|
|
1149
|
+
updateValues(updatedFieldArrayValues);
|
|
1150
|
+
setFields(updatedFieldArrayValues);
|
|
1151
|
+
control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
|
|
1152
|
+
argA: fillEmptyArray(value),
|
|
1153
|
+
});
|
|
1560
1154
|
};
|
|
1561
|
-
const
|
|
1562
|
-
|
|
1155
|
+
const remove = (index) => {
|
|
1156
|
+
if (disabled) {
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
|
|
1160
|
+
ids.current = removeArrayAt(ids.current, index);
|
|
1161
|
+
updateValues(updatedFieldArrayValues);
|
|
1162
|
+
setFields(updatedFieldArrayValues);
|
|
1163
|
+
!Array.isArray(get(control._fields, name)) &&
|
|
1164
|
+
set(control._fields, name, undefined);
|
|
1165
|
+
control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
|
|
1166
|
+
argA: index,
|
|
1167
|
+
});
|
|
1563
1168
|
};
|
|
1564
|
-
|
|
1565
|
-
|
|
1169
|
+
const insert$1 = (index, value, options) => {
|
|
1170
|
+
if (disabled) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
const insertValue = convertToArrayPayload(cloneObject(value));
|
|
1174
|
+
const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
|
|
1175
|
+
control._names.focus = getFocusFieldName(name, index, options);
|
|
1176
|
+
ids.current = insert(ids.current, index, insertValue.map(generateId));
|
|
1177
|
+
updateValues(updatedFieldArrayValues);
|
|
1178
|
+
setFields(updatedFieldArrayValues);
|
|
1179
|
+
control._setFieldArray(name, updatedFieldArrayValues, insert, {
|
|
1180
|
+
argA: index,
|
|
1181
|
+
argB: fillEmptyArray(value),
|
|
1182
|
+
});
|
|
1566
1183
|
};
|
|
1567
|
-
const
|
|
1568
|
-
|
|
1569
|
-
|
|
1184
|
+
const swap = (indexA, indexB) => {
|
|
1185
|
+
if (disabled) {
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
1189
|
+
swapArrayAt(updatedFieldArrayValues, indexA, indexB);
|
|
1190
|
+
swapArrayAt(ids.current, indexA, indexB);
|
|
1191
|
+
updateValues(updatedFieldArrayValues);
|
|
1192
|
+
setFields(updatedFieldArrayValues);
|
|
1193
|
+
control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
|
|
1194
|
+
argA: indexA,
|
|
1195
|
+
argB: indexB,
|
|
1196
|
+
}, false);
|
|
1570
1197
|
};
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1198
|
+
const move = (from, to) => {
|
|
1199
|
+
if (disabled) {
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
1203
|
+
moveArrayAt(updatedFieldArrayValues, from, to);
|
|
1204
|
+
moveArrayAt(ids.current, from, to);
|
|
1205
|
+
updateValues(updatedFieldArrayValues);
|
|
1206
|
+
setFields(updatedFieldArrayValues);
|
|
1207
|
+
control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
|
|
1208
|
+
argA: from,
|
|
1209
|
+
argB: to,
|
|
1210
|
+
}, false);
|
|
1575
1211
|
};
|
|
1576
|
-
const
|
|
1577
|
-
if (
|
|
1212
|
+
const update = (index, value) => {
|
|
1213
|
+
if (disabled) {
|
|
1578
1214
|
return;
|
|
1579
1215
|
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
else {
|
|
1590
|
-
isValid = await executeBuiltInValidation({
|
|
1591
|
-
fields: _fields,
|
|
1592
|
-
onlyCheckValid: true,
|
|
1593
|
-
eventType: EVENTS.VALID,
|
|
1594
|
-
});
|
|
1595
|
-
}
|
|
1596
|
-
if (isValid !== _formState.isValid) {
|
|
1597
|
-
_subjects.state.next({
|
|
1598
|
-
isValid,
|
|
1599
|
-
});
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1216
|
+
const updateValue = cloneObject(value);
|
|
1217
|
+
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
|
|
1218
|
+
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
|
1219
|
+
updateValues(updatedFieldArrayValues);
|
|
1220
|
+
setFields([...updatedFieldArrayValues]);
|
|
1221
|
+
control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
|
|
1222
|
+
argA: index,
|
|
1223
|
+
argB: updateValue,
|
|
1224
|
+
}, true, false);
|
|
1602
1225
|
};
|
|
1603
|
-
const
|
|
1604
|
-
if (
|
|
1605
|
-
|
|
1606
|
-
_proxyFormState.validatingFields ||
|
|
1607
|
-
_proxySubscribeFormState.isValidating ||
|
|
1608
|
-
_proxySubscribeFormState.validatingFields)) {
|
|
1609
|
-
(names || Array.from(_names.mount)).forEach((name) => {
|
|
1610
|
-
if (name) {
|
|
1611
|
-
isValidating
|
|
1612
|
-
? set(_formState.validatingFields, name, isValidating)
|
|
1613
|
-
: unset(_formState.validatingFields, name);
|
|
1614
|
-
}
|
|
1615
|
-
});
|
|
1616
|
-
_subjects.state.next({
|
|
1617
|
-
validatingFields: _formState.validatingFields,
|
|
1618
|
-
isValidating: !isEmptyObject(_formState.validatingFields),
|
|
1619
|
-
});
|
|
1226
|
+
const replace = (value) => {
|
|
1227
|
+
if (disabled) {
|
|
1228
|
+
return;
|
|
1620
1229
|
}
|
|
1230
|
+
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
|
|
1231
|
+
ids.current = updatedFieldArrayValues.map(generateId);
|
|
1232
|
+
updateValues([...updatedFieldArrayValues]);
|
|
1233
|
+
setFields([...updatedFieldArrayValues]);
|
|
1234
|
+
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
|
1621
1235
|
};
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1236
|
+
React.useEffect(() => {
|
|
1237
|
+
if (disabled) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
control._state.action = false;
|
|
1241
|
+
isWatched(name, control._names) &&
|
|
1242
|
+
control._subjects.state.next({
|
|
1243
|
+
...control._formState,
|
|
1244
|
+
});
|
|
1245
|
+
const validationModes = getValidationModes(control._options.mode);
|
|
1246
|
+
if (_actioned.current &&
|
|
1247
|
+
(!validationModes.isOnSubmit || control._formState.isSubmitted) &&
|
|
1248
|
+
!getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
|
1249
|
+
!validationModes.isOnBlur) {
|
|
1250
|
+
if (control._options.resolver) {
|
|
1251
|
+
control._runSchema([name]).then((result) => {
|
|
1252
|
+
var _a, _b;
|
|
1253
|
+
control._updateIsValidating([name]);
|
|
1254
|
+
const error = get(result.errors, name);
|
|
1255
|
+
const existingError = get(control._formState.errors, name);
|
|
1256
|
+
const existingErrorType = existingError && (existingError.type || ((_a = existingError.root) === null || _a === void 0 ? void 0 : _a.type));
|
|
1257
|
+
const existingErrorMessage = existingError &&
|
|
1258
|
+
(existingError.message || ((_b = existingError.root) === null || _b === void 0 ? void 0 : _b.message));
|
|
1259
|
+
if (existingError
|
|
1260
|
+
? (!error && existingErrorType) ||
|
|
1261
|
+
(error &&
|
|
1262
|
+
(existingErrorType !== error.type ||
|
|
1263
|
+
existingErrorMessage !== error.message))
|
|
1264
|
+
: error && error.type) {
|
|
1265
|
+
if (error) {
|
|
1266
|
+
isObject(error) &&
|
|
1267
|
+
!Object.keys(error).some((key) => !Number.isNaN(+key))
|
|
1268
|
+
? updateFieldArrayRootError(control._formState.errors, { [name]: error }, name)
|
|
1269
|
+
: set(control._formState.errors, name, error);
|
|
1270
|
+
}
|
|
1271
|
+
else {
|
|
1272
|
+
unset(control._formState.errors, name);
|
|
1273
|
+
}
|
|
1274
|
+
control._subjects.state.next({
|
|
1275
|
+
errors: control._formState.errors,
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1644
1279
|
}
|
|
1645
|
-
|
|
1646
|
-
|
|
1280
|
+
else {
|
|
1281
|
+
const field = get(control._fields, name);
|
|
1282
|
+
if (field &&
|
|
1283
|
+
field._f &&
|
|
1284
|
+
!(getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
|
1285
|
+
getValidationModes(control._options.mode).isOnSubmit)) {
|
|
1286
|
+
validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
|
|
1287
|
+
control._subjects.state.next({
|
|
1288
|
+
errors: updateFieldArrayRootError(control._formState.errors, error, name),
|
|
1289
|
+
}));
|
|
1290
|
+
}
|
|
1647
1291
|
}
|
|
1648
|
-
|
|
1292
|
+
}
|
|
1293
|
+
// External updates that change `fields` (e.g. reset() or setValue() on
|
|
1294
|
+
// the array) already notify subscribers with the up-to-date values
|
|
1295
|
+
// themselves, so only re-broadcast here for genuine array method calls.
|
|
1296
|
+
_actioned.current &&
|
|
1297
|
+
control._subjects.state.next({
|
|
1649
1298
|
name,
|
|
1650
|
-
|
|
1651
|
-
dirtyFields: _formState.dirtyFields,
|
|
1652
|
-
errors: _formState.errors,
|
|
1653
|
-
isValid: _formState.isValid,
|
|
1299
|
+
values: cloneObject(control._formValues),
|
|
1654
1300
|
});
|
|
1301
|
+
control._names.focus &&
|
|
1302
|
+
iterateFieldsByAction(control._fields, (ref, key) => {
|
|
1303
|
+
if (control._names.focus &&
|
|
1304
|
+
key.startsWith(control._names.focus) &&
|
|
1305
|
+
ref.focus) {
|
|
1306
|
+
ref.focus();
|
|
1307
|
+
return 1;
|
|
1308
|
+
}
|
|
1309
|
+
return;
|
|
1310
|
+
});
|
|
1311
|
+
control._names.focus = '';
|
|
1312
|
+
control._setValid();
|
|
1313
|
+
_actioned.current = false;
|
|
1314
|
+
}, [fields, name, control, disabled]);
|
|
1315
|
+
React.useEffect(() => {
|
|
1316
|
+
if (!disabled) {
|
|
1317
|
+
!get(control._formValues, name) && control._setFieldArray(name);
|
|
1655
1318
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
}
|
|
1659
|
-
};
|
|
1660
|
-
const updateErrors = (name, error) => {
|
|
1661
|
-
set(_formState.errors, name, error);
|
|
1662
|
-
_formState.errors = { ..._formState.errors };
|
|
1663
|
-
_subjects.state.next({
|
|
1664
|
-
errors: _formState.errors,
|
|
1665
|
-
});
|
|
1666
|
-
};
|
|
1667
|
-
const _setErrors = (errors) => {
|
|
1668
|
-
_formState.errors = errors;
|
|
1669
|
-
_subjects.state.next({
|
|
1670
|
-
errors: _formState.errors,
|
|
1671
|
-
isValid: false,
|
|
1672
|
-
});
|
|
1673
|
-
};
|
|
1674
|
-
const hasExplicitNullIntermediate = (name) => {
|
|
1675
|
-
const segments = isKey(name) ? [name] : stringToPath(name);
|
|
1676
|
-
let formValues = _formValues;
|
|
1677
|
-
let defaultValues = _defaultValues;
|
|
1678
|
-
for (let i = 0; i < segments.length - 1; i++) {
|
|
1679
|
-
const key = segments[i];
|
|
1680
|
-
formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
|
|
1681
|
-
defaultValues = isNullOrUndefined(defaultValues)
|
|
1682
|
-
? defaultValues
|
|
1683
|
-
: defaultValues[key];
|
|
1684
|
-
if (formValues === null && defaultValues !== null) {
|
|
1685
|
-
return true;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
return false;
|
|
1689
|
-
};
|
|
1690
|
-
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
|
|
1691
|
-
const field = get(_fields, name);
|
|
1692
|
-
if (field) {
|
|
1693
|
-
if (hasExplicitNullIntermediate(name)) {
|
|
1319
|
+
return () => {
|
|
1320
|
+
if (disabled) {
|
|
1694
1321
|
return;
|
|
1695
1322
|
}
|
|
1696
|
-
const
|
|
1697
|
-
const
|
|
1698
|
-
|
|
1699
|
-
(
|
|
1700
|
-
|
|
1701
|
-
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
|
1702
|
-
: setFieldValue(name, defaultValue);
|
|
1703
|
-
if (_state.mount && !_state.action) {
|
|
1704
|
-
_setValid();
|
|
1705
|
-
if (wasUnsetInFormValues &&
|
|
1706
|
-
_formState.isDirty &&
|
|
1707
|
-
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
|
|
1708
|
-
const isDirty = _getDirty();
|
|
1709
|
-
if (!isDirty) {
|
|
1710
|
-
_formState.isDirty = false;
|
|
1711
|
-
_subjects.state.next({ ..._formState });
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
if (props.shouldUnregister &&
|
|
1715
|
-
wasUnsetInFormValues &&
|
|
1716
|
-
!isUndefined(get(_formValues, name)) &&
|
|
1717
|
-
isWatched(name, _names)) {
|
|
1718
|
-
_state.watch = true;
|
|
1323
|
+
const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
|
|
1324
|
+
const updateMounted = (name, value) => {
|
|
1325
|
+
const field = get(control._fields, name);
|
|
1326
|
+
if (field && field._f) {
|
|
1327
|
+
field._f.mount = value;
|
|
1719
1328
|
}
|
|
1329
|
+
};
|
|
1330
|
+
if (_actioned.current && shouldKeepFieldArrayValues) {
|
|
1331
|
+
control._subjects.state.next({
|
|
1332
|
+
name,
|
|
1333
|
+
values: cloneObject(control._formValues),
|
|
1334
|
+
});
|
|
1720
1335
|
}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
let shouldUpdateField = false;
|
|
1725
|
-
let isPreviousDirty = false;
|
|
1726
|
-
const output = {
|
|
1727
|
-
name,
|
|
1336
|
+
shouldKeepFieldArrayValues
|
|
1337
|
+
? updateMounted(name, false)
|
|
1338
|
+
: control.unregister(name);
|
|
1728
1339
|
};
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1340
|
+
}, [name, control, keyName, shouldUnregister, disabled]);
|
|
1341
|
+
return {
|
|
1342
|
+
swap: React.useCallback(swap, [updateValues, name, control, disabled]),
|
|
1343
|
+
move: React.useCallback(move, [updateValues, name, control, disabled]),
|
|
1344
|
+
prepend: React.useCallback(prepend, [
|
|
1345
|
+
updateValues,
|
|
1346
|
+
name,
|
|
1347
|
+
control,
|
|
1348
|
+
disabled,
|
|
1349
|
+
]),
|
|
1350
|
+
append: React.useCallback(append, [updateValues, name, control, disabled]),
|
|
1351
|
+
remove: React.useCallback(remove, [updateValues, name, control, disabled]),
|
|
1352
|
+
insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
|
|
1353
|
+
update: React.useCallback(update, [updateValues, name, control, disabled]),
|
|
1354
|
+
replace: React.useCallback(replace, [
|
|
1355
|
+
updateValues,
|
|
1356
|
+
name,
|
|
1357
|
+
control,
|
|
1358
|
+
disabled,
|
|
1359
|
+
]),
|
|
1360
|
+
fields: React.useMemo(() => fields.map((field, index) => ({
|
|
1361
|
+
...field,
|
|
1362
|
+
...(isBoolean(disabled) ? { disabled } : {}),
|
|
1363
|
+
[keyName]: ids.current[index] || generateId(),
|
|
1364
|
+
})), [fields, keyName, disabled]),
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Component based on `useFieldArray` hook to work with controlled component.
|
|
1370
|
+
*
|
|
1371
|
+
* @example
|
|
1372
|
+
* ```tsx
|
|
1373
|
+
* function App() {
|
|
1374
|
+
* const { control, register } = useForm<FormValues>({
|
|
1375
|
+
* defaultValues: {
|
|
1376
|
+
* test: [
|
|
1377
|
+
* {
|
|
1378
|
+
* value: '',
|
|
1379
|
+
* },
|
|
1380
|
+
* ],
|
|
1381
|
+
* },
|
|
1382
|
+
* });
|
|
1383
|
+
*
|
|
1384
|
+
* return (
|
|
1385
|
+
* <form>
|
|
1386
|
+
* <FieldArray
|
|
1387
|
+
* control={control}
|
|
1388
|
+
* name="test"
|
|
1389
|
+
* render={({ fields }) =>
|
|
1390
|
+
* fields.map((field, index) => (
|
|
1391
|
+
* <input key={field.id} {...register(`test.${index}.value`)} />
|
|
1392
|
+
* ))
|
|
1393
|
+
* }
|
|
1394
|
+
* />
|
|
1395
|
+
* </form>
|
|
1396
|
+
* );
|
|
1397
|
+
* }
|
|
1398
|
+
* ```
|
|
1399
|
+
*/
|
|
1400
|
+
const FieldArray = (props) => props.render(useFieldArray(props));
|
|
1401
|
+
|
|
1402
|
+
const flatten = (obj) => {
|
|
1403
|
+
const output = {};
|
|
1404
|
+
for (const key of Object.keys(obj)) {
|
|
1405
|
+
if (isObjectType(obj[key]) &&
|
|
1406
|
+
obj[key] !== null &&
|
|
1407
|
+
!isDateObject(obj[key])) {
|
|
1408
|
+
const nested = flatten(obj[key]);
|
|
1409
|
+
for (const nestedKey of Object.keys(nested)) {
|
|
1410
|
+
output[`${key}.${nestedKey}`] = nested[nestedKey];
|
|
1753
1411
|
}
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1412
|
+
}
|
|
1413
|
+
else {
|
|
1414
|
+
output[key] = obj[key];
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
return output;
|
|
1418
|
+
};
|
|
1419
|
+
|
|
1420
|
+
const HookFormContext = React.createContext(null);
|
|
1421
|
+
HookFormContext.displayName = 'HookFormContext';
|
|
1422
|
+
/**
|
|
1423
|
+
* This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
|
|
1424
|
+
*
|
|
1425
|
+
* @remarks
|
|
1426
|
+
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
1427
|
+
*
|
|
1428
|
+
* @returns return all useForm methods
|
|
1429
|
+
*
|
|
1430
|
+
* @example
|
|
1431
|
+
* ```tsx
|
|
1432
|
+
* function App() {
|
|
1433
|
+
* const methods = useForm();
|
|
1434
|
+
* const onSubmit = data => console.log(data);
|
|
1435
|
+
*
|
|
1436
|
+
* return (
|
|
1437
|
+
* <FormProvider {...methods} >
|
|
1438
|
+
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
1439
|
+
* <NestedInput />
|
|
1440
|
+
* <input type="submit" />
|
|
1441
|
+
* </form>
|
|
1442
|
+
* </FormProvider>
|
|
1443
|
+
* );
|
|
1444
|
+
* }
|
|
1445
|
+
*
|
|
1446
|
+
* function NestedInput() {
|
|
1447
|
+
* const { register } = useFormContext(); // retrieve all hook methods
|
|
1448
|
+
* return <input {...register("test")} />;
|
|
1449
|
+
* }
|
|
1450
|
+
* ```
|
|
1451
|
+
*/
|
|
1452
|
+
const useFormContext = () => React.useContext(HookFormContext);
|
|
1453
|
+
/**
|
|
1454
|
+
* A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
|
|
1455
|
+
*
|
|
1456
|
+
* @remarks
|
|
1457
|
+
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
1458
|
+
*
|
|
1459
|
+
* @param props - all useForm methods
|
|
1460
|
+
*
|
|
1461
|
+
* @example
|
|
1462
|
+
* ```tsx
|
|
1463
|
+
* function App() {
|
|
1464
|
+
* const methods = useForm();
|
|
1465
|
+
* const onSubmit = data => console.log(data);
|
|
1466
|
+
*
|
|
1467
|
+
* return (
|
|
1468
|
+
* <FormProvider {...methods} >
|
|
1469
|
+
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
1470
|
+
* <NestedInput />
|
|
1471
|
+
* <input type="submit" />
|
|
1472
|
+
* </form>
|
|
1473
|
+
* </FormProvider>
|
|
1474
|
+
* );
|
|
1475
|
+
* }
|
|
1476
|
+
*
|
|
1477
|
+
* function NestedInput() {
|
|
1478
|
+
* const { register } = useFormContext(); // retrieve all hook methods
|
|
1479
|
+
* return <input {...register("test")} />;
|
|
1480
|
+
* }
|
|
1481
|
+
* ```
|
|
1482
|
+
*/
|
|
1483
|
+
const FormProvider = ({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
|
|
1484
|
+
const memoizedValue = React.useMemo(() => ({
|
|
1485
|
+
watch,
|
|
1486
|
+
getValues,
|
|
1487
|
+
getFieldState,
|
|
1488
|
+
setError,
|
|
1489
|
+
clearErrors,
|
|
1490
|
+
setValue,
|
|
1491
|
+
setValues,
|
|
1492
|
+
trigger,
|
|
1493
|
+
formState,
|
|
1494
|
+
resetField,
|
|
1495
|
+
reset,
|
|
1496
|
+
resetDefaultValues,
|
|
1497
|
+
handleSubmit,
|
|
1498
|
+
unregister,
|
|
1499
|
+
control,
|
|
1500
|
+
register,
|
|
1501
|
+
setFocus,
|
|
1502
|
+
subscribe,
|
|
1503
|
+
}), [
|
|
1504
|
+
clearErrors,
|
|
1505
|
+
control,
|
|
1506
|
+
formState,
|
|
1507
|
+
getFieldState,
|
|
1508
|
+
getValues,
|
|
1509
|
+
handleSubmit,
|
|
1510
|
+
register,
|
|
1511
|
+
reset,
|
|
1512
|
+
resetDefaultValues,
|
|
1513
|
+
resetField,
|
|
1514
|
+
setError,
|
|
1515
|
+
setFocus,
|
|
1516
|
+
setValue,
|
|
1517
|
+
setValues,
|
|
1518
|
+
subscribe,
|
|
1519
|
+
trigger,
|
|
1520
|
+
unregister,
|
|
1521
|
+
watch,
|
|
1522
|
+
]);
|
|
1523
|
+
return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
|
|
1524
|
+
React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
const POST_REQUEST = 'post';
|
|
1528
|
+
/**
|
|
1529
|
+
* Form component to manage submission.
|
|
1530
|
+
*
|
|
1531
|
+
* @param props - to setup submission detail. {@link FormProps}
|
|
1532
|
+
*
|
|
1533
|
+
* @returns form component or headless render prop.
|
|
1534
|
+
*
|
|
1535
|
+
* @example
|
|
1536
|
+
* ```tsx
|
|
1537
|
+
* function App() {
|
|
1538
|
+
* const { control, formState: { errors } } = useForm();
|
|
1539
|
+
*
|
|
1540
|
+
* return (
|
|
1541
|
+
* <Form action="/api" control={control}>
|
|
1542
|
+
* <input {...register("name")} />
|
|
1543
|
+
* <p>{errors?.root?.server && 'Server error'}</p>
|
|
1544
|
+
* <button>Submit</button>
|
|
1545
|
+
* </Form>
|
|
1546
|
+
* );
|
|
1547
|
+
* }
|
|
1548
|
+
* ```
|
|
1549
|
+
*/
|
|
1550
|
+
function Form(props) {
|
|
1551
|
+
const methods = useFormContext();
|
|
1552
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1553
|
+
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
|
|
1554
|
+
const submit = React.useCallback(async (event) => {
|
|
1555
|
+
let hasError = false;
|
|
1556
|
+
let type = '';
|
|
1557
|
+
await control.handleSubmit(async (data) => {
|
|
1558
|
+
const formData = new FormData();
|
|
1559
|
+
let formDataJson = '';
|
|
1560
|
+
try {
|
|
1561
|
+
formDataJson = JSON.stringify(data);
|
|
1562
|
+
}
|
|
1563
|
+
catch (_a) { }
|
|
1564
|
+
const flattenFormValues = flatten(data);
|
|
1565
|
+
for (const key in flattenFormValues) {
|
|
1566
|
+
formData.append(key, flattenFormValues[key]);
|
|
1567
|
+
}
|
|
1568
|
+
if (onSubmit) {
|
|
1569
|
+
await onSubmit({
|
|
1570
|
+
data,
|
|
1571
|
+
event,
|
|
1572
|
+
method,
|
|
1573
|
+
formData,
|
|
1574
|
+
formDataJson,
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
if (action) {
|
|
1578
|
+
try {
|
|
1579
|
+
const shouldStringifySubmissionData = [
|
|
1580
|
+
headers && headers['Content-Type'],
|
|
1581
|
+
encType,
|
|
1582
|
+
].some((value) => value && value.includes('json'));
|
|
1583
|
+
const response = await fetch(String(action), {
|
|
1584
|
+
method,
|
|
1585
|
+
headers: {
|
|
1586
|
+
...headers,
|
|
1587
|
+
...(encType && encType !== 'multipart/form-data'
|
|
1588
|
+
? { 'Content-Type': encType }
|
|
1589
|
+
: {}),
|
|
1590
|
+
},
|
|
1591
|
+
body: shouldStringifySubmissionData ? formDataJson : formData,
|
|
1592
|
+
});
|
|
1593
|
+
if (response &&
|
|
1594
|
+
(validateStatus
|
|
1595
|
+
? !validateStatus(response.status)
|
|
1596
|
+
: response.status < 200 || response.status >= 300)) {
|
|
1597
|
+
hasError = true;
|
|
1598
|
+
onError && onError({ response });
|
|
1599
|
+
type = String(response.status);
|
|
1600
|
+
}
|
|
1601
|
+
else {
|
|
1602
|
+
onSuccess && onSuccess({ response });
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
catch (error) {
|
|
1606
|
+
hasError = true;
|
|
1607
|
+
onError && onError({ error });
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
})(event);
|
|
1611
|
+
if (hasError && control) {
|
|
1612
|
+
control._subjects.state.next({
|
|
1613
|
+
isSubmitSuccessful: false,
|
|
1614
|
+
});
|
|
1615
|
+
control.setError('root.server', {
|
|
1616
|
+
type,
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
}, [
|
|
1620
|
+
control,
|
|
1621
|
+
onSubmit,
|
|
1622
|
+
method,
|
|
1623
|
+
action,
|
|
1624
|
+
headers,
|
|
1625
|
+
encType,
|
|
1626
|
+
validateStatus,
|
|
1627
|
+
onError,
|
|
1628
|
+
onSuccess,
|
|
1629
|
+
]);
|
|
1630
|
+
React.useEffect(() => {
|
|
1631
|
+
setMounted(true);
|
|
1632
|
+
}, []);
|
|
1633
|
+
return render ? (React.createElement(React.Fragment, null, render({
|
|
1634
|
+
submit,
|
|
1635
|
+
}))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
|
|
1639
|
+
|
|
1640
|
+
var createSubject = () => {
|
|
1641
|
+
let _observers = [];
|
|
1642
|
+
const next = (value) => {
|
|
1643
|
+
for (const observer of _observers) {
|
|
1644
|
+
observer.next && observer.next(value);
|
|
1645
|
+
}
|
|
1646
|
+
};
|
|
1647
|
+
const subscribe = (observer) => {
|
|
1648
|
+
_observers.push(observer);
|
|
1649
|
+
return {
|
|
1650
|
+
unsubscribe: () => {
|
|
1651
|
+
_observers = _observers.filter((o) => o !== observer);
|
|
1652
|
+
},
|
|
1653
|
+
};
|
|
1654
|
+
};
|
|
1655
|
+
const unsubscribe = () => {
|
|
1656
|
+
_observers = [];
|
|
1657
|
+
};
|
|
1658
|
+
return {
|
|
1659
|
+
get observers() {
|
|
1660
|
+
return _observers;
|
|
1661
|
+
},
|
|
1662
|
+
next,
|
|
1663
|
+
subscribe,
|
|
1664
|
+
unsubscribe,
|
|
1665
|
+
};
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1668
|
+
function extractFormValues(fieldsState, formValues) {
|
|
1669
|
+
const values = {};
|
|
1670
|
+
for (const key in fieldsState) {
|
|
1671
|
+
if (fieldsState.hasOwnProperty(key)) {
|
|
1672
|
+
const fieldState = fieldsState[key];
|
|
1673
|
+
const fieldValue = formValues[key];
|
|
1674
|
+
if (fieldState && isObject(fieldState) && fieldValue) {
|
|
1675
|
+
const nestedFieldsState = extractFormValues(fieldState, fieldValue);
|
|
1676
|
+
if (isObject(nestedFieldsState)) {
|
|
1677
|
+
values[key] = nestedFieldsState;
|
|
1764
1678
|
}
|
|
1765
1679
|
}
|
|
1766
|
-
|
|
1680
|
+
else if (fieldsState[key]) {
|
|
1681
|
+
values[key] = fieldValue;
|
|
1682
|
+
}
|
|
1767
1683
|
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1684
|
+
}
|
|
1685
|
+
return values;
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
|
1689
|
+
|
|
1690
|
+
var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
|
1691
|
+
|
|
1692
|
+
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
|
1693
|
+
|
|
1694
|
+
var objectHasFunction = (data) => {
|
|
1695
|
+
for (const key in data) {
|
|
1696
|
+
if (isFunction(data[key])) {
|
|
1697
|
+
return true;
|
|
1778
1698
|
}
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1699
|
+
}
|
|
1700
|
+
return false;
|
|
1701
|
+
};
|
|
1702
|
+
|
|
1703
|
+
function isTraversable(value) {
|
|
1704
|
+
return Array.isArray(value) || (isObject(value) && !objectHasFunction(value));
|
|
1705
|
+
}
|
|
1706
|
+
function isRegisteredLeaf(fieldRef) {
|
|
1707
|
+
return !!(fieldRef && '_f' in fieldRef);
|
|
1708
|
+
}
|
|
1709
|
+
function isEmptyDirtyContainer(value) {
|
|
1710
|
+
return Array.isArray(value)
|
|
1711
|
+
? !value.some((item) => !isUndefined(item))
|
|
1712
|
+
: !Object.keys(value).length;
|
|
1713
|
+
}
|
|
1714
|
+
function clearDirtyField(container, key) {
|
|
1715
|
+
if (Array.isArray(container)) {
|
|
1716
|
+
container[key] = undefined;
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
delete container[key];
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
function markFieldsDirty(data, fields = {}, fieldRefs) {
|
|
1723
|
+
for (const key in data) {
|
|
1724
|
+
const value = data[key];
|
|
1725
|
+
const fieldRef = fieldRefs && fieldRefs[key];
|
|
1726
|
+
if (isTraversable(value) &&
|
|
1727
|
+
(!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
|
|
1728
|
+
fields[key] = Array.isArray(value) ? [] : {};
|
|
1729
|
+
markFieldsDirty(value, fields[key], fieldRef);
|
|
1730
|
+
if (isEmptyDirtyContainer(fields[key])) {
|
|
1731
|
+
clearDirtyField(fields, key);
|
|
1732
|
+
}
|
|
1786
1733
|
}
|
|
1787
|
-
if (
|
|
1788
|
-
|
|
1789
|
-
shouldUpdateValid) {
|
|
1790
|
-
const updatedFormState = {
|
|
1791
|
-
...fieldState,
|
|
1792
|
-
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
|
1793
|
-
errors: _formState.errors,
|
|
1794
|
-
name,
|
|
1795
|
-
};
|
|
1796
|
-
_formState = {
|
|
1797
|
-
..._formState,
|
|
1798
|
-
...updatedFormState,
|
|
1799
|
-
};
|
|
1800
|
-
_subjects.state.next(updatedFormState);
|
|
1734
|
+
else if (!isUndefined(value)) {
|
|
1735
|
+
fields[key] = true;
|
|
1801
1736
|
}
|
|
1802
|
-
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
!Object.keys(error).some((key) => !Number.isNaN(Number(key)))
|
|
1817
|
-
? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
|
|
1818
|
-
: set(_formState.errors, name, error)
|
|
1819
|
-
: unset(_formState.errors, name);
|
|
1737
|
+
}
|
|
1738
|
+
return fields;
|
|
1739
|
+
}
|
|
1740
|
+
function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
|
|
1741
|
+
if (!dirtyFieldsFromValues) {
|
|
1742
|
+
dirtyFieldsFromValues = markFieldsDirty(formValues, {}, fieldRefs);
|
|
1743
|
+
}
|
|
1744
|
+
for (const key in data) {
|
|
1745
|
+
const value = data[key];
|
|
1746
|
+
const fieldRef = fieldRefs && fieldRefs[key];
|
|
1747
|
+
if (isTraversable(value) &&
|
|
1748
|
+
(!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
|
|
1749
|
+
if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
|
|
1750
|
+
dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}, fieldRef);
|
|
1820
1751
|
}
|
|
1821
|
-
|
|
1752
|
+
else {
|
|
1753
|
+
getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key], fieldRef);
|
|
1754
|
+
}
|
|
1755
|
+
if (isEmptyDirtyContainer(dirtyFieldsFromValues[key])) {
|
|
1756
|
+
clearDirtyField(dirtyFieldsFromValues, key);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
else if (deepEqual(value, formValues[key])) {
|
|
1760
|
+
clearDirtyField(dirtyFieldsFromValues, key);
|
|
1822
1761
|
}
|
|
1823
1762
|
else {
|
|
1824
|
-
|
|
1763
|
+
dirtyFieldsFromValues[key] = true;
|
|
1825
1764
|
}
|
|
1826
|
-
|
|
1765
|
+
}
|
|
1766
|
+
return dirtyFieldsFromValues;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
|
1770
|
+
? value
|
|
1771
|
+
: valueAsNumber
|
|
1772
|
+
? value === ''
|
|
1773
|
+
? NaN
|
|
1774
|
+
: value
|
|
1775
|
+
? +value
|
|
1776
|
+
: value
|
|
1777
|
+
: valueAsDate && isString(value)
|
|
1778
|
+
? new Date(value)
|
|
1779
|
+
: setValueAs
|
|
1780
|
+
? setValueAs(value)
|
|
1781
|
+
: value;
|
|
1782
|
+
|
|
1783
|
+
function getFieldValue(_f) {
|
|
1784
|
+
const ref = _f.ref;
|
|
1785
|
+
if (isFileInput(ref)) {
|
|
1786
|
+
return ref.files;
|
|
1787
|
+
}
|
|
1788
|
+
if (isRadioInput(ref)) {
|
|
1789
|
+
return getRadioValue(_f.refs).value;
|
|
1790
|
+
}
|
|
1791
|
+
if (isMultipleSelect(ref)) {
|
|
1792
|
+
return [...ref.selectedOptions].map(({ value }) => value);
|
|
1793
|
+
}
|
|
1794
|
+
if (isCheckBoxInput(ref)) {
|
|
1795
|
+
return getCheckboxValue(_f.refs).value;
|
|
1796
|
+
}
|
|
1797
|
+
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
|
1801
|
+
const fields = {};
|
|
1802
|
+
for (const name of fieldsNames) {
|
|
1803
|
+
const field = get(_fields, name);
|
|
1804
|
+
field && set(fields, name, field._f);
|
|
1805
|
+
}
|
|
1806
|
+
return {
|
|
1807
|
+
criteriaMode,
|
|
1808
|
+
names: [...fieldsNames],
|
|
1809
|
+
fields,
|
|
1810
|
+
shouldUseNativeValidation,
|
|
1827
1811
|
};
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
}
|
|
1853
|
-
else {
|
|
1854
|
-
clearErrors(FORM_ERROR_TYPE);
|
|
1812
|
+
};
|
|
1813
|
+
|
|
1814
|
+
var getRuleValue = (rule) => isUndefined(rule)
|
|
1815
|
+
? rule
|
|
1816
|
+
: isRegex(rule)
|
|
1817
|
+
? rule.source
|
|
1818
|
+
: isObject(rule)
|
|
1819
|
+
? isRegex(rule.value)
|
|
1820
|
+
? rule.value.source
|
|
1821
|
+
: rule.value
|
|
1822
|
+
: rule;
|
|
1823
|
+
|
|
1824
|
+
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
1825
|
+
var hasPromiseValidation = (fieldReference) => {
|
|
1826
|
+
if (!fieldReference || !fieldReference.validate)
|
|
1827
|
+
return false;
|
|
1828
|
+
if (isFunction(fieldReference.validate)) {
|
|
1829
|
+
return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
|
|
1830
|
+
}
|
|
1831
|
+
if (isObject(fieldReference.validate)) {
|
|
1832
|
+
for (const key in fieldReference.validate) {
|
|
1833
|
+
if (fieldReference.validate[key].constructor
|
|
1834
|
+
.name === ASYNC_FUNCTION) {
|
|
1835
|
+
return true;
|
|
1855
1836
|
}
|
|
1856
|
-
return result;
|
|
1857
1837
|
}
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1838
|
+
}
|
|
1839
|
+
return false;
|
|
1840
|
+
};
|
|
1841
|
+
|
|
1842
|
+
var hasValidation = (options) => options.mount &&
|
|
1843
|
+
(options.required ||
|
|
1844
|
+
options.min ||
|
|
1845
|
+
options.max ||
|
|
1846
|
+
options.maxLength ||
|
|
1847
|
+
options.minLength ||
|
|
1848
|
+
options.pattern ||
|
|
1849
|
+
options.validate);
|
|
1850
|
+
|
|
1851
|
+
function schemaErrorLookup(errors, _fields, name) {
|
|
1852
|
+
const error = get(errors, name);
|
|
1853
|
+
if (error || isKey(name)) {
|
|
1854
|
+
return {
|
|
1855
|
+
error,
|
|
1856
|
+
name,
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
const names = name.split('.');
|
|
1860
|
+
while (names.length) {
|
|
1861
|
+
const fieldName = names.join('.');
|
|
1862
|
+
const field = get(_fields, fieldName);
|
|
1863
|
+
const foundError = get(errors, fieldName);
|
|
1864
|
+
if (field && !Array.isArray(field) && name !== fieldName) {
|
|
1865
|
+
return { name };
|
|
1876
1866
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
const isFieldArrayRoot = _names.array.has(_f.name);
|
|
1883
|
-
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
|
|
1884
|
-
const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
|
|
1885
|
-
_proxyFormState.isValidating ||
|
|
1886
|
-
_proxySubscribeFormState.validatingFields ||
|
|
1887
|
-
_proxySubscribeFormState.isValidating;
|
|
1888
|
-
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
1889
|
-
_updateIsValidating([_f.name], true);
|
|
1890
|
-
}
|
|
1891
|
-
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
|
|
1892
|
-
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
1893
|
-
_updateIsValidating([_f.name]);
|
|
1894
|
-
}
|
|
1895
|
-
if (fieldError[_f.name]) {
|
|
1896
|
-
context.valid = false;
|
|
1897
|
-
if (onlyCheckValid) {
|
|
1898
|
-
break;
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
!onlyCheckValid &&
|
|
1902
|
-
(get(fieldError, _f.name)
|
|
1903
|
-
? isFieldArrayRoot
|
|
1904
|
-
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
|
1905
|
-
: set(_formState.errors, _f.name, fieldError[_f.name])
|
|
1906
|
-
: unset(_formState.errors, _f.name));
|
|
1907
|
-
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
|
|
1908
|
-
break;
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
!isEmptyObject(fieldValue) &&
|
|
1912
|
-
(await executeBuiltInValidation({
|
|
1913
|
-
context,
|
|
1914
|
-
onlyCheckValid,
|
|
1915
|
-
fields: fieldValue,
|
|
1916
|
-
name: name,
|
|
1917
|
-
eventType,
|
|
1918
|
-
}));
|
|
1919
|
-
}
|
|
1867
|
+
if (foundError && foundError.type) {
|
|
1868
|
+
return {
|
|
1869
|
+
name: fieldName,
|
|
1870
|
+
error: foundError,
|
|
1871
|
+
};
|
|
1920
1872
|
}
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
field &&
|
|
1927
|
-
(field._f.refs
|
|
1928
|
-
? field._f.refs.every((ref) => !live(ref))
|
|
1929
|
-
: !live(field._f.ref)) &&
|
|
1930
|
-
unregister(name);
|
|
1873
|
+
if (foundError && foundError.root && foundError.root.type) {
|
|
1874
|
+
return {
|
|
1875
|
+
name: `${fieldName}.root`,
|
|
1876
|
+
error: foundError.root,
|
|
1877
|
+
};
|
|
1931
1878
|
}
|
|
1932
|
-
|
|
1879
|
+
names.pop();
|
|
1880
|
+
}
|
|
1881
|
+
return {
|
|
1882
|
+
name,
|
|
1933
1883
|
};
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
else {
|
|
1984
|
-
fieldReference.ref.value = fieldValue;
|
|
1985
|
-
if (!fieldReference.ref.type && !skipRender) {
|
|
1986
|
-
_subjects.state.next({
|
|
1987
|
-
name,
|
|
1988
|
-
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
1989
|
-
});
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
1887
|
+
updateFormState(formStateData);
|
|
1888
|
+
const { name, ...formState } = formStateData;
|
|
1889
|
+
const keys = Object.keys(formState);
|
|
1890
|
+
return (!keys.length ||
|
|
1891
|
+
(isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
|
|
1892
|
+
keys.find((key) => _proxyFormState[key] ===
|
|
1893
|
+
(!isRoot || VALIDATION_MODE.all)));
|
|
1894
|
+
};
|
|
1895
|
+
|
|
1896
|
+
var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
|
1897
|
+
!signalName ||
|
|
1898
|
+
name === signalName ||
|
|
1899
|
+
convertToArrayPayload(name).some((currentName) => currentName &&
|
|
1900
|
+
(exact
|
|
1901
|
+
? currentName === signalName || currentName.startsWith(signalName + '.')
|
|
1902
|
+
: currentName.startsWith(signalName) ||
|
|
1903
|
+
signalName.startsWith(currentName)));
|
|
1904
|
+
|
|
1905
|
+
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
|
|
1906
|
+
if (mode.isOnAll) {
|
|
1907
|
+
return false;
|
|
1908
|
+
}
|
|
1909
|
+
else if (!isSubmitted && mode.isOnTouch) {
|
|
1910
|
+
return !(isTouched || isBlurEvent);
|
|
1911
|
+
}
|
|
1912
|
+
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
|
|
1913
|
+
return !isBlurEvent;
|
|
1914
|
+
}
|
|
1915
|
+
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
|
|
1916
|
+
return isBlurEvent;
|
|
1917
|
+
}
|
|
1918
|
+
return true;
|
|
1919
|
+
};
|
|
1920
|
+
|
|
1921
|
+
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
|
1922
|
+
|
|
1923
|
+
const defaultOptions = {
|
|
1924
|
+
mode: VALIDATION_MODE.onSubmit,
|
|
1925
|
+
reValidateMode: VALIDATION_MODE.onChange,
|
|
1926
|
+
shouldFocusError: true,
|
|
1927
|
+
};
|
|
1928
|
+
const FORM_ERROR_TYPE = 'form';
|
|
1929
|
+
const updateDirtyFields = (dirtyFields, nextDirtyFields) => {
|
|
1930
|
+
for (const key in dirtyFields) {
|
|
1931
|
+
if (!(key in nextDirtyFields)) {
|
|
1932
|
+
delete dirtyFields[key];
|
|
1993
1933
|
}
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1934
|
+
}
|
|
1935
|
+
Object.assign(dirtyFields, nextDirtyFields);
|
|
1936
|
+
};
|
|
1937
|
+
const DEFAULT_FORM_STATE = {
|
|
1938
|
+
submitCount: 0,
|
|
1939
|
+
isDirty: false,
|
|
1940
|
+
isReady: false,
|
|
1941
|
+
isValidating: false,
|
|
1942
|
+
isSubmitted: false,
|
|
1943
|
+
isSubmitting: false,
|
|
1944
|
+
isSubmitSuccessful: false,
|
|
1945
|
+
isValid: false,
|
|
1946
|
+
touchedFields: {},
|
|
1947
|
+
dirtyFields: {},
|
|
1948
|
+
validatingFields: {},
|
|
1949
|
+
};
|
|
1950
|
+
function createFormControl(props = {}) {
|
|
1951
|
+
let _options = {
|
|
1952
|
+
...defaultOptions,
|
|
1953
|
+
...props,
|
|
1954
|
+
};
|
|
1955
|
+
let _formState = {
|
|
1956
|
+
...cloneObject(DEFAULT_FORM_STATE),
|
|
1957
|
+
isLoading: isFunction(_options.defaultValues),
|
|
1958
|
+
errors: _options.errors || {},
|
|
1959
|
+
disabled: _options.disabled || false,
|
|
1960
|
+
};
|
|
1961
|
+
let _fields = {};
|
|
1962
|
+
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
|
|
1963
|
+
? cloneObject(_options.defaultValues || _options.values) || {}
|
|
1964
|
+
: {};
|
|
1965
|
+
let _formValues = _options.shouldUnregister
|
|
1966
|
+
? {}
|
|
1967
|
+
: cloneObject(_defaultValues);
|
|
1968
|
+
let _state = {
|
|
1969
|
+
action: false,
|
|
1970
|
+
mount: false,
|
|
1971
|
+
watch: false,
|
|
1972
|
+
keepIsValid: false,
|
|
1997
1973
|
};
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
const field = get(_fields, fieldName);
|
|
2006
|
-
(_names.array.has(name) ||
|
|
2007
|
-
isObject(fieldValue) ||
|
|
2008
|
-
(field && !field._f)) &&
|
|
2009
|
-
!isDateObject(fieldValue)
|
|
2010
|
-
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
2011
|
-
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
2012
|
-
}
|
|
1974
|
+
let _names = {
|
|
1975
|
+
mount: new Set(),
|
|
1976
|
+
disabled: new Set(),
|
|
1977
|
+
unMount: new Set(),
|
|
1978
|
+
array: new Set(),
|
|
1979
|
+
watch: new Set(),
|
|
1980
|
+
registerName: new Set(),
|
|
2013
1981
|
};
|
|
2014
|
-
const
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
});
|
|
2028
|
-
if ((_proxyFormState.isDirty ||
|
|
2029
|
-
_proxyFormState.dirtyFields ||
|
|
2030
|
-
_proxySubscribeFormState.isDirty ||
|
|
2031
|
-
_proxySubscribeFormState.dirtyFields) &&
|
|
2032
|
-
options.shouldDirty) {
|
|
2033
|
-
_updateDirtyFields();
|
|
2034
|
-
if (!skipStateEmit) {
|
|
2035
|
-
_subjects.state.next({
|
|
2036
|
-
name,
|
|
2037
|
-
dirtyFields: _formState.dirtyFields,
|
|
2038
|
-
isDirty: _getDirty(name, cloneValue),
|
|
2039
|
-
});
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
else {
|
|
2044
|
-
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
2045
|
-
isEmptyObject(cloneValue);
|
|
2046
|
-
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
2047
|
-
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2048
|
-
}
|
|
2049
|
-
else {
|
|
2050
|
-
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
if (!isValueUnchanged && !skipStateEmit) {
|
|
2054
|
-
const watched = isWatched(name, _names);
|
|
2055
|
-
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
2056
|
-
_subjects.state.next({
|
|
2057
|
-
...(watched && _formState),
|
|
2058
|
-
name: _state.mount || watched ? name : undefined,
|
|
2059
|
-
values,
|
|
2060
|
-
});
|
|
2061
|
-
}
|
|
1982
|
+
const delayErrorCallbacks = {};
|
|
1983
|
+
const timers = {};
|
|
1984
|
+
let _valuesSubscriberCount = 0;
|
|
1985
|
+
let _validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
1986
|
+
let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1987
|
+
const defaultProxyFormState = {
|
|
1988
|
+
isDirty: false,
|
|
1989
|
+
dirtyFields: false,
|
|
1990
|
+
validatingFields: false,
|
|
1991
|
+
touchedFields: false,
|
|
1992
|
+
isValidating: false,
|
|
1993
|
+
isValid: false,
|
|
1994
|
+
errors: false,
|
|
2062
1995
|
};
|
|
2063
|
-
const
|
|
2064
|
-
|
|
2065
|
-
const updatedFormValues = isFunction(formValues)
|
|
2066
|
-
? formValues(_formValues)
|
|
2067
|
-
: formValues;
|
|
2068
|
-
if (!deepEqual(_formValues, updatedFormValues)) {
|
|
2069
|
-
_formValues = {
|
|
2070
|
-
..._formValues,
|
|
2071
|
-
...updatedFormValues,
|
|
2072
|
-
};
|
|
2073
|
-
const flattenedUpdates = flatten(updatedFormValues);
|
|
2074
|
-
for (const fieldName of _names.mount) {
|
|
2075
|
-
if (fieldName in flattenedUpdates) {
|
|
2076
|
-
_setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
|
|
2077
|
-
}
|
|
2078
|
-
}
|
|
2079
|
-
_subjects.state.next({
|
|
2080
|
-
..._formState,
|
|
2081
|
-
name: undefined,
|
|
2082
|
-
type: undefined,
|
|
2083
|
-
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
2084
|
-
});
|
|
2085
|
-
if (options.shouldValidate) {
|
|
2086
|
-
_setValid();
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
1996
|
+
const _proxyFormState = {
|
|
1997
|
+
...defaultProxyFormState,
|
|
2089
1998
|
};
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
const target = event.target;
|
|
2093
|
-
let name = target.name;
|
|
2094
|
-
let isFieldValueUpdated = true;
|
|
2095
|
-
const field = get(_fields, name);
|
|
2096
|
-
const _updateIsFieldValueUpdated = (fieldValue) => {
|
|
2097
|
-
isFieldValueUpdated =
|
|
2098
|
-
Number.isNaN(fieldValue) ||
|
|
2099
|
-
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
2100
|
-
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
2101
|
-
};
|
|
2102
|
-
if (field) {
|
|
2103
|
-
let error;
|
|
2104
|
-
let isValid;
|
|
2105
|
-
const fieldValue = target.type
|
|
2106
|
-
? getFieldValue(field._f)
|
|
2107
|
-
: getEventValue(event);
|
|
2108
|
-
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
2109
|
-
const hasNoValidationEffect = !hasValidation(field._f) &&
|
|
2110
|
-
!props.validate &&
|
|
2111
|
-
!_options.resolver &&
|
|
2112
|
-
!get(_formState.errors, name) &&
|
|
2113
|
-
!field._f.deps;
|
|
2114
|
-
const shouldSkipValidation = hasNoValidationEffect ||
|
|
2115
|
-
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
|
|
2116
|
-
const watched = isWatched(name, _names, isBlurEvent);
|
|
2117
|
-
set(_formValues, name, fieldValue);
|
|
2118
|
-
if (isBlurEvent) {
|
|
2119
|
-
if (!target || !target.readOnly) {
|
|
2120
|
-
field._f.onBlur && field._f.onBlur(event);
|
|
2121
|
-
delayErrorCallback && delayErrorCallback(0);
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2124
|
-
else if (field._f.onChange) {
|
|
2125
|
-
field._f.onChange(event);
|
|
2126
|
-
}
|
|
2127
|
-
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
|
|
2128
|
-
const shouldRender = !isEmptyObject(fieldState) || watched;
|
|
2129
|
-
!isBlurEvent &&
|
|
2130
|
-
_subjects.state.next({
|
|
2131
|
-
name,
|
|
2132
|
-
type: event.type,
|
|
2133
|
-
...(_valuesSubscriberCount
|
|
2134
|
-
? { values: cloneObject(_formValues) }
|
|
2135
|
-
: {}),
|
|
2136
|
-
});
|
|
2137
|
-
if (shouldSkipValidation) {
|
|
2138
|
-
if ((!hasNoValidationEffect || !_formState.isValid) &&
|
|
2139
|
-
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
|
|
2140
|
-
if (_options.mode === 'onBlur') {
|
|
2141
|
-
if (isBlurEvent) {
|
|
2142
|
-
_setValid();
|
|
2143
|
-
}
|
|
2144
|
-
}
|
|
2145
|
-
else if (!isBlurEvent) {
|
|
2146
|
-
_setValid();
|
|
2147
|
-
}
|
|
2148
|
-
}
|
|
2149
|
-
return (shouldRender &&
|
|
2150
|
-
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
|
|
2151
|
-
}
|
|
2152
|
-
if (!_options.resolver && props.validate) {
|
|
2153
|
-
await validateForm({
|
|
2154
|
-
name: name,
|
|
2155
|
-
eventType: event.type,
|
|
2156
|
-
});
|
|
2157
|
-
}
|
|
2158
|
-
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
|
|
2159
|
-
if (_options.resolver) {
|
|
2160
|
-
const { errors } = await _runSchema([name]);
|
|
2161
|
-
_updateIsValidating([name]);
|
|
2162
|
-
_updateIsFieldValueUpdated(fieldValue);
|
|
2163
|
-
if (!isFieldValueUpdated) {
|
|
2164
|
-
!isEmptyObject(fieldState) && _subjects.state.next(fieldState);
|
|
2165
|
-
return;
|
|
2166
|
-
}
|
|
2167
|
-
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
|
2168
|
-
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
|
2169
|
-
error = errorLookupResult.error;
|
|
2170
|
-
name = errorLookupResult.name;
|
|
2171
|
-
isValid = isEmptyObject(errors);
|
|
2172
|
-
}
|
|
2173
|
-
else {
|
|
2174
|
-
_updateIsValidating([name], true);
|
|
2175
|
-
error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
|
|
2176
|
-
_updateIsValidating([name]);
|
|
2177
|
-
_updateIsFieldValueUpdated(fieldValue);
|
|
2178
|
-
if (isFieldValueUpdated) {
|
|
2179
|
-
if (error) {
|
|
2180
|
-
isValid = false;
|
|
2181
|
-
}
|
|
2182
|
-
else if (_proxyFormState.isValid ||
|
|
2183
|
-
_proxySubscribeFormState.isValid) {
|
|
2184
|
-
isValid = await executeBuiltInValidation({
|
|
2185
|
-
fields: _fields,
|
|
2186
|
-
onlyCheckValid: true,
|
|
2187
|
-
name: name,
|
|
2188
|
-
eventType: event.type,
|
|
2189
|
-
});
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
if (isFieldValueUpdated) {
|
|
2194
|
-
field._f.deps &&
|
|
2195
|
-
(!Array.isArray(field._f.deps) || field._f.deps.length > 0) &&
|
|
2196
|
-
trigger(field._f.deps);
|
|
2197
|
-
shouldRenderByError(name, isValid, error, fieldState);
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
1999
|
+
let _proxySubscribeFormState = {
|
|
2000
|
+
..._proxyFormState,
|
|
2200
2001
|
};
|
|
2201
|
-
const
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
return 1;
|
|
2205
|
-
}
|
|
2206
|
-
return;
|
|
2002
|
+
const _subjects = {
|
|
2003
|
+
array: createSubject(),
|
|
2004
|
+
state: createSubject(),
|
|
2207
2005
|
};
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
: isValid;
|
|
2006
|
+
let _setValidCallId = 0;
|
|
2007
|
+
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
|
2008
|
+
const debounce = (name, callback) => (wait) => {
|
|
2009
|
+
clearTimeout(timers[name]);
|
|
2010
|
+
timers[name] = setTimeout(callback, wait);
|
|
2011
|
+
};
|
|
2012
|
+
const _setValid = async (shouldUpdateValid) => {
|
|
2013
|
+
if (_state.keepIsValid) {
|
|
2014
|
+
return;
|
|
2218
2015
|
}
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2016
|
+
if (!_options.disabled &&
|
|
2017
|
+
(_proxyFormState.isValid ||
|
|
2018
|
+
_proxySubscribeFormState.isValid ||
|
|
2019
|
+
shouldUpdateValid)) {
|
|
2020
|
+
const callId = ++_setValidCallId;
|
|
2021
|
+
let isValid;
|
|
2022
|
+
if (_options.resolver) {
|
|
2023
|
+
isValid = isEmptyObject((await _runSchema()).errors);
|
|
2024
|
+
callId === _setValidCallId && _updateIsValidating();
|
|
2025
|
+
}
|
|
2026
|
+
else {
|
|
2027
|
+
isValid = await executeBuiltInValidation({
|
|
2028
|
+
fields: _fields,
|
|
2029
|
+
onlyCheckValid: true,
|
|
2030
|
+
eventType: EVENTS.VALID,
|
|
2225
2031
|
});
|
|
2226
|
-
}
|
|
2227
|
-
|
|
2032
|
+
}
|
|
2033
|
+
if (callId === _setValidCallId && isValid !== _formState.isValid) {
|
|
2034
|
+
_subjects.state.next({
|
|
2035
|
+
isValid,
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2228
2038
|
}
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2039
|
+
};
|
|
2040
|
+
const _updateIsValidating = (names, isValidating) => {
|
|
2041
|
+
if (!_options.disabled &&
|
|
2042
|
+
(_proxyFormState.isValidating ||
|
|
2043
|
+
_proxyFormState.validatingFields ||
|
|
2044
|
+
_proxySubscribeFormState.isValidating ||
|
|
2045
|
+
_proxySubscribeFormState.validatingFields)) {
|
|
2046
|
+
(names || Array.from(_names.mount)).forEach((name) => {
|
|
2047
|
+
if (name) {
|
|
2048
|
+
isValidating
|
|
2049
|
+
? set(_formState.validatingFields, name, isValidating)
|
|
2050
|
+
: unset(_formState.validatingFields, name);
|
|
2051
|
+
}
|
|
2052
|
+
});
|
|
2053
|
+
_subjects.state.next({
|
|
2054
|
+
validatingFields: _formState.validatingFields,
|
|
2055
|
+
isValidating: !isEmptyObject(_formState.validatingFields),
|
|
2234
2056
|
});
|
|
2235
2057
|
}
|
|
2236
|
-
_subjects.state.next({
|
|
2237
|
-
...(!isString(name) ||
|
|
2238
|
-
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
2239
|
-
isValid !== _formState.isValid)
|
|
2240
|
-
? {}
|
|
2241
|
-
: { name }),
|
|
2242
|
-
...(_options.resolver || !name ? { isValid } : {}),
|
|
2243
|
-
errors: _formState.errors,
|
|
2244
|
-
});
|
|
2245
|
-
options.shouldFocus &&
|
|
2246
|
-
!validationResult &&
|
|
2247
|
-
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
|
2248
|
-
return validationResult;
|
|
2249
2058
|
};
|
|
2250
|
-
const
|
|
2251
|
-
|
|
2252
|
-
...(_state.mount ? _formValues : _defaultValues),
|
|
2253
|
-
};
|
|
2254
|
-
if (config) {
|
|
2255
|
-
values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
|
|
2256
|
-
}
|
|
2257
|
-
return isUndefined(fieldNames)
|
|
2258
|
-
? values
|
|
2259
|
-
: isString(fieldNames)
|
|
2260
|
-
? get(values, fieldNames)
|
|
2261
|
-
: fieldNames.map((name) => get(values, name));
|
|
2059
|
+
const _updateDirtyFields = () => {
|
|
2060
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
2262
2061
|
};
|
|
2263
|
-
const
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2062
|
+
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
|
2063
|
+
if (args && method && !_options.disabled) {
|
|
2064
|
+
_state.action = true;
|
|
2065
|
+
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
|
|
2066
|
+
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
|
2067
|
+
shouldSetValues && set(_fields, name, fieldValues);
|
|
2068
|
+
}
|
|
2069
|
+
if (shouldUpdateFieldsAndState &&
|
|
2070
|
+
Array.isArray(get(_formState.errors, name))) {
|
|
2071
|
+
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
|
2072
|
+
shouldSetValues && set(_formState.errors, name, errors);
|
|
2073
|
+
unsetEmptyArray(_formState.errors, name);
|
|
2074
|
+
}
|
|
2075
|
+
if ((_proxyFormState.touchedFields ||
|
|
2076
|
+
_proxySubscribeFormState.touchedFields) &&
|
|
2077
|
+
shouldUpdateFieldsAndState &&
|
|
2078
|
+
Array.isArray(get(_formState.touchedFields, name))) {
|
|
2079
|
+
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
|
2080
|
+
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
|
2081
|
+
}
|
|
2082
|
+
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
|
2083
|
+
_updateDirtyFields();
|
|
2084
|
+
}
|
|
2085
|
+
_subjects.state.next({
|
|
2086
|
+
name,
|
|
2087
|
+
isDirty: _getDirty(name, values),
|
|
2088
|
+
dirtyFields: _formState.dirtyFields,
|
|
2089
|
+
errors: _formState.errors,
|
|
2090
|
+
isValid: _formState.isValid,
|
|
2279
2091
|
});
|
|
2280
2092
|
}
|
|
2281
2093
|
else {
|
|
2282
|
-
|
|
2283
|
-
errors: {},
|
|
2284
|
-
});
|
|
2094
|
+
set(_formValues, name, values);
|
|
2285
2095
|
}
|
|
2286
2096
|
};
|
|
2287
|
-
const
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
...restOfErrorTree,
|
|
2293
|
-
...error,
|
|
2294
|
-
ref,
|
|
2097
|
+
const updateErrors = (name, error) => {
|
|
2098
|
+
set(_formState.errors, name, error);
|
|
2099
|
+
_formState.errors = { ..._formState.errors };
|
|
2100
|
+
_subjects.state.next({
|
|
2101
|
+
errors: _formState.errors,
|
|
2295
2102
|
});
|
|
2103
|
+
};
|
|
2104
|
+
const _setErrors = (errors) => {
|
|
2105
|
+
_formState.errors = errors;
|
|
2296
2106
|
_subjects.state.next({
|
|
2297
|
-
name,
|
|
2298
2107
|
errors: _formState.errors,
|
|
2299
2108
|
isValid: false,
|
|
2300
2109
|
});
|
|
2301
|
-
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
2302
2110
|
};
|
|
2303
|
-
const
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2111
|
+
const hasExplicitNullIntermediate = (name) => {
|
|
2112
|
+
const segments = isKey(name) ? [name] : stringToPath(name);
|
|
2113
|
+
let formValues = _formValues;
|
|
2114
|
+
let defaultValues = _defaultValues;
|
|
2115
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
2116
|
+
const key = segments[i];
|
|
2117
|
+
formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
|
|
2118
|
+
defaultValues = isNullOrUndefined(defaultValues)
|
|
2119
|
+
? defaultValues
|
|
2120
|
+
: defaultValues[key];
|
|
2121
|
+
if (formValues === null && defaultValues !== null) {
|
|
2122
|
+
return true;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
return false;
|
|
2126
|
+
};
|
|
2127
|
+
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
|
|
2128
|
+
const field = get(_fields, name);
|
|
2129
|
+
if (field) {
|
|
2130
|
+
if (hasExplicitNullIntermediate(name)) {
|
|
2131
|
+
return;
|
|
2132
|
+
}
|
|
2133
|
+
const wasUnsetInFormValues = isUndefined(get(_formValues, name));
|
|
2134
|
+
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
|
|
2135
|
+
isUndefined(defaultValue) ||
|
|
2136
|
+
(ref && ref.defaultChecked) ||
|
|
2137
|
+
shouldSkipSetValueAs
|
|
2138
|
+
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
|
2139
|
+
: setFieldValue(name, defaultValue);
|
|
2140
|
+
if (_state.mount && !_state.action) {
|
|
2141
|
+
_setValid();
|
|
2142
|
+
if (wasUnsetInFormValues &&
|
|
2143
|
+
_formState.isDirty &&
|
|
2144
|
+
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
|
|
2145
|
+
const isDirty = _getDirty();
|
|
2146
|
+
if (!isDirty) {
|
|
2147
|
+
_formState.isDirty = false;
|
|
2148
|
+
_subjects.state.next({ ..._formState });
|
|
2315
2149
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2150
|
+
}
|
|
2151
|
+
if (props.shouldUnregister &&
|
|
2152
|
+
wasUnsetInFormValues &&
|
|
2153
|
+
!isUndefined(get(_formValues, name)) &&
|
|
2154
|
+
isWatched(name, _names)) {
|
|
2155
|
+
_state.watch = true;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2321
2158
|
}
|
|
2322
|
-
return _getWatch(name, defaultValue, true);
|
|
2323
2159
|
};
|
|
2324
|
-
const
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2160
|
+
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
|
2161
|
+
let shouldUpdateField = false;
|
|
2162
|
+
let isPreviousDirty = false;
|
|
2163
|
+
const output = {
|
|
2164
|
+
name,
|
|
2165
|
+
};
|
|
2166
|
+
// an explicit programmatic update (e.g. setValue with shouldDirty: true)
|
|
2167
|
+
// opts into dirty tracking even when the form is disabled
|
|
2168
|
+
if (!_options.disabled || shouldDirty === true) {
|
|
2169
|
+
if (!isBlurEvent || shouldDirty) {
|
|
2170
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
2171
|
+
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
2172
|
+
isPreviousDirty = _formState.isDirty;
|
|
2173
|
+
_formState.isDirty = output.isDirty =
|
|
2174
|
+
!isCurrentFieldPristine || _getDirty();
|
|
2175
|
+
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
2176
|
+
}
|
|
2177
|
+
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
2178
|
+
if (isCurrentFieldPristine !== _formState.isDirty) {
|
|
2179
|
+
updateDirtyFields(_formState.dirtyFields, getDirtyFields(_defaultValues, _formValues, undefined, _fields));
|
|
2180
|
+
}
|
|
2181
|
+
else {
|
|
2182
|
+
isCurrentFieldPristine
|
|
2183
|
+
? unset(_formState.dirtyFields, name)
|
|
2184
|
+
: set(_formState.dirtyFields, name, true);
|
|
2185
|
+
}
|
|
2186
|
+
output.dirtyFields = _formState.dirtyFields;
|
|
2187
|
+
shouldUpdateField =
|
|
2188
|
+
shouldUpdateField ||
|
|
2189
|
+
((_proxyFormState.dirtyFields ||
|
|
2190
|
+
_proxySubscribeFormState.dirtyFields) &&
|
|
2191
|
+
isPreviousDirty !== !isCurrentFieldPristine);
|
|
2192
|
+
}
|
|
2193
|
+
if (isBlurEvent) {
|
|
2194
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
|
2195
|
+
if (!isPreviousFieldTouched) {
|
|
2196
|
+
set(_formState.touchedFields, name, isBlurEvent);
|
|
2197
|
+
output.touchedFields = _formState.touchedFields;
|
|
2198
|
+
shouldUpdateField =
|
|
2199
|
+
shouldUpdateField ||
|
|
2200
|
+
((_proxyFormState.touchedFields ||
|
|
2201
|
+
_proxySubscribeFormState.touchedFields) &&
|
|
2202
|
+
isPreviousFieldTouched !== isBlurEvent);
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
|
2206
|
+
}
|
|
2207
|
+
return shouldUpdateField ? output : {};
|
|
2208
|
+
};
|
|
2209
|
+
const shouldRenderByError = (name, isValid, error, fieldState) => {
|
|
2210
|
+
const previousFieldError = get(_formState.errors, name);
|
|
2211
|
+
const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
2212
|
+
isBoolean(isValid) &&
|
|
2213
|
+
_formState.isValid !== isValid;
|
|
2214
|
+
if (_options.delayError && error) {
|
|
2215
|
+
delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
|
|
2216
|
+
delayErrorCallbacks[name](_options.delayError);
|
|
2217
|
+
}
|
|
2218
|
+
else {
|
|
2219
|
+
clearTimeout(timers[name]);
|
|
2220
|
+
delete delayErrorCallbacks[name];
|
|
2221
|
+
error
|
|
2222
|
+
? set(_formState.errors, name, error)
|
|
2223
|
+
: unset(_formState.errors, name);
|
|
2224
|
+
_formState.errors = { ..._formState.errors };
|
|
2329
2225
|
}
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
}
|
|
2343
|
-
|
|
2344
|
-
if (!needsValues) {
|
|
2345
|
-
return unsubscribe;
|
|
2226
|
+
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
|
2227
|
+
!isEmptyObject(fieldState) ||
|
|
2228
|
+
shouldUpdateValid) {
|
|
2229
|
+
const updatedFormState = {
|
|
2230
|
+
...fieldState,
|
|
2231
|
+
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
|
2232
|
+
errors: _formState.errors,
|
|
2233
|
+
name,
|
|
2234
|
+
};
|
|
2235
|
+
_formState = {
|
|
2236
|
+
..._formState,
|
|
2237
|
+
...updatedFormState,
|
|
2238
|
+
};
|
|
2239
|
+
_subjects.state.next(updatedFormState);
|
|
2346
2240
|
}
|
|
2347
|
-
let called = false;
|
|
2348
|
-
return () => {
|
|
2349
|
-
if (called) {
|
|
2350
|
-
return;
|
|
2351
|
-
}
|
|
2352
|
-
called = true;
|
|
2353
|
-
_valuesSubscriberCount--;
|
|
2354
|
-
unsubscribe();
|
|
2355
|
-
};
|
|
2356
2241
|
};
|
|
2357
|
-
const
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
..._proxySubscribeFormState,
|
|
2361
|
-
...props.formState,
|
|
2362
|
-
};
|
|
2363
|
-
return _subscribe({
|
|
2364
|
-
...props,
|
|
2365
|
-
formState: {
|
|
2366
|
-
...defaultProxyFormState,
|
|
2367
|
-
...props.formState,
|
|
2368
|
-
},
|
|
2369
|
-
});
|
|
2242
|
+
const _runSchema = async (name) => {
|
|
2243
|
+
_updateIsValidating(name, true);
|
|
2244
|
+
return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
|
|
2370
2245
|
};
|
|
2371
|
-
const
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2246
|
+
const executeSchemaAndUpdateState = async (names) => {
|
|
2247
|
+
const { errors } = await _runSchema(names);
|
|
2248
|
+
_updateIsValidating(names);
|
|
2249
|
+
if (names) {
|
|
2250
|
+
for (const name of names) {
|
|
2251
|
+
const error = get(errors, name);
|
|
2252
|
+
error
|
|
2253
|
+
? _names.array.has(name) &&
|
|
2254
|
+
isObject(error) &&
|
|
2255
|
+
!Object.keys(error).some((key) => !Number.isNaN(Number(key)))
|
|
2256
|
+
? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
|
|
2257
|
+
: set(_formState.errors, name, error)
|
|
2258
|
+
: unset(_formState.errors, name);
|
|
2378
2259
|
}
|
|
2379
|
-
|
|
2380
|
-
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
|
2381
|
-
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
|
2382
|
-
!options.keepIsValidating &&
|
|
2383
|
-
unset(_formState.validatingFields, fieldName);
|
|
2384
|
-
!_options.shouldUnregister &&
|
|
2385
|
-
!options.keepDefaultValue &&
|
|
2386
|
-
unset(_defaultValues, fieldName);
|
|
2260
|
+
_formState.errors = { ..._formState.errors };
|
|
2387
2261
|
}
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
});
|
|
2391
|
-
_subjects.state.next({
|
|
2392
|
-
..._formState,
|
|
2393
|
-
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
|
2394
|
-
});
|
|
2395
|
-
!options.keepIsValid && _setValid();
|
|
2396
|
-
};
|
|
2397
|
-
const _setDisabledField = ({ disabled, name, }) => {
|
|
2398
|
-
if ((isBoolean(disabled) && _state.mount) ||
|
|
2399
|
-
!!disabled ||
|
|
2400
|
-
_names.disabled.has(name)) {
|
|
2401
|
-
const wasDisabled = _names.disabled.has(name);
|
|
2402
|
-
const isDisabled = !!disabled;
|
|
2403
|
-
const disabledStateChanged = wasDisabled !== isDisabled;
|
|
2404
|
-
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
|
2405
|
-
disabledStateChanged && _state.mount && !_state.action && _setValid();
|
|
2262
|
+
else {
|
|
2263
|
+
_formState.errors = errors;
|
|
2406
2264
|
}
|
|
2265
|
+
return errors;
|
|
2407
2266
|
};
|
|
2408
|
-
const
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
...(field || {}),
|
|
2414
|
-
_f: {
|
|
2415
|
-
...(field && field._f ? field._f : { ref: { name } }),
|
|
2267
|
+
const validateForm = async ({ name, eventType, }) => {
|
|
2268
|
+
if (props.validate) {
|
|
2269
|
+
const result = await props.validate({
|
|
2270
|
+
formValues: _formValues,
|
|
2271
|
+
formState: _formState,
|
|
2416
2272
|
name,
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2273
|
+
eventType,
|
|
2274
|
+
});
|
|
2275
|
+
if (isObject(result)) {
|
|
2276
|
+
for (const key in result) {
|
|
2277
|
+
const error = result[key];
|
|
2278
|
+
if (error) {
|
|
2279
|
+
setError(`${FORM_ERROR_TYPE}.${key}`, {
|
|
2280
|
+
message: isString(error.message) ? error.message : '',
|
|
2281
|
+
type: error.type || INPUT_VALIDATION_RULES.validate,
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
else if (isString(result) || !result) {
|
|
2287
|
+
setError(FORM_ERROR_TYPE, {
|
|
2288
|
+
message: result || '',
|
|
2289
|
+
type: INPUT_VALIDATION_RULES.validate,
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2292
|
+
else {
|
|
2293
|
+
clearErrors(FORM_ERROR_TYPE);
|
|
2294
|
+
}
|
|
2295
|
+
return result;
|
|
2296
|
+
}
|
|
2297
|
+
return true;
|
|
2298
|
+
};
|
|
2299
|
+
const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
|
|
2300
|
+
valid: true,
|
|
2301
|
+
runRootValidation: false,
|
|
2302
|
+
}, }) => {
|
|
2303
|
+
if (props.validate) {
|
|
2304
|
+
context.runRootValidation = true;
|
|
2305
|
+
const result = await validateForm({
|
|
2427
2306
|
name,
|
|
2307
|
+
eventType,
|
|
2428
2308
|
});
|
|
2309
|
+
if (!result) {
|
|
2310
|
+
context.valid = false;
|
|
2311
|
+
if (onlyCheckValid) {
|
|
2312
|
+
return context.valid;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2429
2315
|
}
|
|
2430
|
-
|
|
2431
|
-
|
|
2316
|
+
for (const name in fields) {
|
|
2317
|
+
const field = fields[name];
|
|
2318
|
+
if (field) {
|
|
2319
|
+
const { _f, ...fieldValue } = field;
|
|
2320
|
+
if (_f) {
|
|
2321
|
+
const isFieldArrayRoot = _names.array.has(_f.name);
|
|
2322
|
+
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
|
|
2323
|
+
const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
|
|
2324
|
+
_proxyFormState.isValidating ||
|
|
2325
|
+
_proxySubscribeFormState.validatingFields ||
|
|
2326
|
+
_proxySubscribeFormState.isValidating;
|
|
2327
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
2328
|
+
_updateIsValidating([_f.name], true);
|
|
2329
|
+
}
|
|
2330
|
+
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
|
|
2331
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
2332
|
+
_updateIsValidating([_f.name]);
|
|
2333
|
+
}
|
|
2334
|
+
if (fieldError[_f.name]) {
|
|
2335
|
+
context.valid = false;
|
|
2336
|
+
if (onlyCheckValid) {
|
|
2337
|
+
break;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
!onlyCheckValid &&
|
|
2341
|
+
(get(fieldError, _f.name)
|
|
2342
|
+
? isFieldArrayRoot
|
|
2343
|
+
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
|
2344
|
+
: set(_formState.errors, _f.name, fieldError[_f.name])
|
|
2345
|
+
: unset(_formState.errors, _f.name));
|
|
2346
|
+
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
|
|
2347
|
+
break;
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
!isEmptyObject(fieldValue) &&
|
|
2351
|
+
(await executeBuiltInValidation({
|
|
2352
|
+
context,
|
|
2353
|
+
onlyCheckValid,
|
|
2354
|
+
fields: fieldValue,
|
|
2355
|
+
name: name,
|
|
2356
|
+
eventType,
|
|
2357
|
+
}));
|
|
2358
|
+
}
|
|
2432
2359
|
}
|
|
2433
|
-
return
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2360
|
+
return context.valid;
|
|
2361
|
+
};
|
|
2362
|
+
const _removeUnmounted = () => {
|
|
2363
|
+
for (const name of _names.unMount) {
|
|
2364
|
+
const field = get(_fields, name);
|
|
2365
|
+
field &&
|
|
2366
|
+
(field._f.refs
|
|
2367
|
+
? field._f.refs.every((ref) => !live(ref))
|
|
2368
|
+
: !live(field._f.ref)) &&
|
|
2369
|
+
unregister(name);
|
|
2370
|
+
}
|
|
2371
|
+
_names.unMount = new Set();
|
|
2372
|
+
};
|
|
2373
|
+
const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
|
|
2374
|
+
!deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
|
|
2375
|
+
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
|
2376
|
+
...(_state.mount
|
|
2377
|
+
? _formValues
|
|
2378
|
+
: isUndefined(defaultValue)
|
|
2379
|
+
? _defaultValues
|
|
2380
|
+
: isString(names)
|
|
2381
|
+
? { [names]: defaultValue }
|
|
2382
|
+
: defaultValue),
|
|
2383
|
+
}, isGlobal, defaultValue);
|
|
2384
|
+
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
|
2385
|
+
const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
|
|
2386
|
+
const field = get(_fields, name);
|
|
2387
|
+
let fieldValue = value;
|
|
2388
|
+
if (field) {
|
|
2389
|
+
const fieldReference = field._f;
|
|
2390
|
+
if (fieldReference) {
|
|
2391
|
+
!fieldReference.disabled &&
|
|
2392
|
+
set(_formValues, name, getFieldValueAs(value, fieldReference));
|
|
2393
|
+
fieldValue =
|
|
2394
|
+
isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
|
|
2395
|
+
? ''
|
|
2396
|
+
: value;
|
|
2397
|
+
if (isMultipleSelect(fieldReference.ref)) {
|
|
2398
|
+
[...fieldReference.ref.options].forEach((optionRef) => (optionRef.selected = fieldValue.includes(optionRef.value)));
|
|
2445
2399
|
}
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
_names.registerName.add(name);
|
|
2453
|
-
register(name, options);
|
|
2454
|
-
_names.registerName.delete(name);
|
|
2455
|
-
field = get(_fields, name);
|
|
2456
|
-
const fieldRef = isUndefined(ref.value)
|
|
2457
|
-
? ref.querySelectorAll
|
|
2458
|
-
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
|
2459
|
-
: ref
|
|
2460
|
-
: ref;
|
|
2461
|
-
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
|
2462
|
-
const refs = field._f.refs || [];
|
|
2463
|
-
if (radioOrCheckbox
|
|
2464
|
-
? refs.find((option) => option === fieldRef)
|
|
2465
|
-
: fieldRef === field._f.ref) {
|
|
2466
|
-
return;
|
|
2467
|
-
}
|
|
2468
|
-
set(_fields, name, {
|
|
2469
|
-
_f: {
|
|
2470
|
-
...field._f,
|
|
2471
|
-
...(radioOrCheckbox
|
|
2472
|
-
? {
|
|
2473
|
-
refs: [
|
|
2474
|
-
...refs.filter(live),
|
|
2475
|
-
fieldRef,
|
|
2476
|
-
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
|
2477
|
-
],
|
|
2478
|
-
ref: { type: fieldRef.type, name },
|
|
2400
|
+
else if (fieldReference.refs) {
|
|
2401
|
+
if (isCheckBoxInput(fieldReference.ref)) {
|
|
2402
|
+
fieldReference.refs.forEach((checkboxRef) => {
|
|
2403
|
+
if (!checkboxRef.defaultChecked || !checkboxRef.disabled) {
|
|
2404
|
+
if (Array.isArray(fieldValue)) {
|
|
2405
|
+
checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value);
|
|
2479
2406
|
}
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2407
|
+
else {
|
|
2408
|
+
checkboxRef.checked =
|
|
2409
|
+
fieldValue === checkboxRef.value || !!fieldValue;
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
else {
|
|
2415
|
+
fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
|
|
2489
2416
|
}
|
|
2490
|
-
(_options.shouldUnregister || options.shouldUnregister) &&
|
|
2491
|
-
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
|
2492
|
-
_names.unMount.add(name);
|
|
2493
2417
|
}
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
iterateFieldsByAction(_fields, (ref, name) => {
|
|
2504
|
-
const currentField = get(_fields, name);
|
|
2505
|
-
if (currentField) {
|
|
2506
|
-
ref.disabled = currentField._f.disabled || disabled;
|
|
2507
|
-
if (Array.isArray(currentField._f.refs)) {
|
|
2508
|
-
currentField._f.refs.forEach((inputRef) => {
|
|
2509
|
-
inputRef.disabled = currentField._f.disabled || disabled;
|
|
2418
|
+
else if (isFileInput(fieldReference.ref)) {
|
|
2419
|
+
fieldReference.ref.value = '';
|
|
2420
|
+
}
|
|
2421
|
+
else {
|
|
2422
|
+
fieldReference.ref.value = fieldValue;
|
|
2423
|
+
if (!fieldReference.ref.type && !skipRender) {
|
|
2424
|
+
_subjects.state.next({
|
|
2425
|
+
name,
|
|
2426
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
2510
2427
|
});
|
|
2511
2428
|
}
|
|
2512
2429
|
}
|
|
2513
|
-
}
|
|
2514
|
-
}
|
|
2515
|
-
};
|
|
2516
|
-
const handleSubmit = (onValid, onInvalid) => async (e) => {
|
|
2517
|
-
let onValidError = undefined;
|
|
2518
|
-
if (e) {
|
|
2519
|
-
e.preventDefault && e.preventDefault();
|
|
2520
|
-
e.persist &&
|
|
2521
|
-
e.persist();
|
|
2522
|
-
}
|
|
2523
|
-
let fieldValues = cloneObject(_formValues);
|
|
2524
|
-
_subjects.state.next({
|
|
2525
|
-
isSubmitting: true,
|
|
2526
|
-
});
|
|
2527
|
-
if (_options.resolver) {
|
|
2528
|
-
const { errors, values } = await _runSchema();
|
|
2529
|
-
_updateIsValidating();
|
|
2530
|
-
_formState.errors = errors;
|
|
2531
|
-
fieldValues = cloneObject(values);
|
|
2430
|
+
}
|
|
2532
2431
|
}
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2432
|
+
(options.shouldDirty || options.shouldTouch) &&
|
|
2433
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
|
|
2434
|
+
options.shouldValidate &&
|
|
2435
|
+
trigger(name, {
|
|
2436
|
+
delayError: options.delayError,
|
|
2537
2437
|
});
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2438
|
+
};
|
|
2439
|
+
const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
|
|
2440
|
+
for (const fieldKey in value) {
|
|
2441
|
+
if (!value.hasOwnProperty(fieldKey)) {
|
|
2442
|
+
return;
|
|
2542
2443
|
}
|
|
2444
|
+
const fieldValue = value[fieldKey];
|
|
2445
|
+
const fieldName = name + '.' + fieldKey;
|
|
2446
|
+
const field = get(_fields, fieldName);
|
|
2447
|
+
(_names.array.has(name) ||
|
|
2448
|
+
isObject(fieldValue) ||
|
|
2449
|
+
(field && !field._f)) &&
|
|
2450
|
+
!isDateObject(fieldValue)
|
|
2451
|
+
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
2452
|
+
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
2543
2453
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2454
|
+
};
|
|
2455
|
+
const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
|
|
2456
|
+
const field = get(_fields, name);
|
|
2457
|
+
const isFieldArray = _names.array.has(name);
|
|
2458
|
+
const cloneValue = skipClone ? value : cloneObject(value);
|
|
2459
|
+
const previousValue = get(_formValues, name);
|
|
2460
|
+
const isValueUnchanged = deepEqual(previousValue, cloneValue);
|
|
2461
|
+
if (!isValueUnchanged) {
|
|
2462
|
+
set(_formValues, name, cloneValue);
|
|
2463
|
+
}
|
|
2464
|
+
if (isFieldArray) {
|
|
2465
|
+
_subjects.array.next({
|
|
2466
|
+
name,
|
|
2467
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
2548
2468
|
});
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2469
|
+
if ((_proxyFormState.isDirty ||
|
|
2470
|
+
_proxyFormState.dirtyFields ||
|
|
2471
|
+
_proxySubscribeFormState.isDirty ||
|
|
2472
|
+
_proxySubscribeFormState.dirtyFields) &&
|
|
2473
|
+
options.shouldDirty) {
|
|
2474
|
+
_updateDirtyFields();
|
|
2475
|
+
if (!skipStateEmit) {
|
|
2476
|
+
_subjects.state.next({
|
|
2477
|
+
name,
|
|
2478
|
+
dirtyFields: _formState.dirtyFields,
|
|
2479
|
+
isDirty: _getDirty(name, cloneValue),
|
|
2480
|
+
});
|
|
2481
|
+
}
|
|
2554
2482
|
}
|
|
2555
2483
|
}
|
|
2556
2484
|
else {
|
|
2557
|
-
|
|
2558
|
-
|
|
2485
|
+
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
2486
|
+
isEmptyObject(cloneValue);
|
|
2487
|
+
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
2488
|
+
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2489
|
+
}
|
|
2490
|
+
else {
|
|
2491
|
+
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2559
2492
|
}
|
|
2560
|
-
_focusError();
|
|
2561
|
-
setTimeout(_focusError);
|
|
2562
2493
|
}
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
throw onValidError;
|
|
2494
|
+
if (!isValueUnchanged && !skipStateEmit) {
|
|
2495
|
+
const watched = isWatched(name, _names);
|
|
2496
|
+
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
2497
|
+
_subjects.state.next({
|
|
2498
|
+
...(watched && _formState),
|
|
2499
|
+
name: _state.mount || watched ? name : undefined,
|
|
2500
|
+
values,
|
|
2501
|
+
});
|
|
2572
2502
|
}
|
|
2573
2503
|
};
|
|
2574
|
-
const
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
|
2590
|
-
: _getDirty();
|
|
2504
|
+
const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
|
|
2505
|
+
const setValues = (formValues, options = {}) => {
|
|
2506
|
+
const updatedFormValues = isFunction(formValues)
|
|
2507
|
+
? formValues(_formValues)
|
|
2508
|
+
: formValues;
|
|
2509
|
+
if (!deepEqual(_formValues, updatedFormValues)) {
|
|
2510
|
+
_formValues = {
|
|
2511
|
+
..._formValues,
|
|
2512
|
+
...updatedFormValues,
|
|
2513
|
+
};
|
|
2514
|
+
const flattenedUpdates = flatten(updatedFormValues);
|
|
2515
|
+
for (const fieldName of _names.mount) {
|
|
2516
|
+
if (fieldName in flattenedUpdates) {
|
|
2517
|
+
_setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
|
|
2518
|
+
}
|
|
2591
2519
|
}
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2520
|
+
_subjects.state.next({
|
|
2521
|
+
..._formState,
|
|
2522
|
+
name: undefined,
|
|
2523
|
+
type: undefined,
|
|
2524
|
+
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
2525
|
+
});
|
|
2526
|
+
if (options.shouldValidate) {
|
|
2527
|
+
_setValid();
|
|
2595
2528
|
}
|
|
2596
|
-
_subjects.state.next({ ..._formState });
|
|
2597
2529
|
}
|
|
2598
2530
|
};
|
|
2599
|
-
const
|
|
2600
|
-
|
|
2601
|
-
const
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2531
|
+
const onChange = async (event) => {
|
|
2532
|
+
_state.mount = true;
|
|
2533
|
+
const target = event.target;
|
|
2534
|
+
let name = target.name;
|
|
2535
|
+
let isFieldValueUpdated = true;
|
|
2536
|
+
const field = get(_fields, name);
|
|
2537
|
+
const _updateIsFieldValueUpdated = (fieldValue) => {
|
|
2538
|
+
isFieldValueUpdated =
|
|
2539
|
+
Number.isNaN(fieldValue) ||
|
|
2540
|
+
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
2541
|
+
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
2542
|
+
};
|
|
2543
|
+
if (field) {
|
|
2544
|
+
let error;
|
|
2545
|
+
let isValid;
|
|
2546
|
+
const fieldValue = target.type
|
|
2547
|
+
? getFieldValue(field._f)
|
|
2548
|
+
: getEventValue(event);
|
|
2549
|
+
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
2550
|
+
const hasNoValidationEffect = !hasValidation(field._f) &&
|
|
2551
|
+
!props.validate &&
|
|
2552
|
+
!_options.resolver &&
|
|
2553
|
+
!get(_formState.errors, name) &&
|
|
2554
|
+
!field._f.deps;
|
|
2555
|
+
const shouldSkipValidation = hasNoValidationEffect ||
|
|
2556
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
|
|
2557
|
+
const watched = isWatched(name, _names, isBlurEvent);
|
|
2558
|
+
set(_formValues, name, fieldValue);
|
|
2559
|
+
if (isBlurEvent) {
|
|
2560
|
+
if (!target || !target.readOnly) {
|
|
2561
|
+
field._f.onBlur && field._f.onBlur(event);
|
|
2562
|
+
const pendingDelayError = delayErrorCallbacks[name];
|
|
2563
|
+
pendingDelayError && pendingDelayError(0);
|
|
2623
2564
|
}
|
|
2624
2565
|
}
|
|
2625
|
-
else {
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2566
|
+
else if (field._f.onChange) {
|
|
2567
|
+
field._f.onChange(event);
|
|
2568
|
+
}
|
|
2569
|
+
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
|
|
2570
|
+
const shouldRender = !isEmptyObject(fieldState) || watched;
|
|
2571
|
+
!isBlurEvent &&
|
|
2572
|
+
_subjects.state.next({
|
|
2573
|
+
name,
|
|
2574
|
+
type: event.type,
|
|
2575
|
+
...(_valuesSubscriberCount
|
|
2576
|
+
? { values: cloneObject(_formValues) }
|
|
2577
|
+
: {}),
|
|
2578
|
+
});
|
|
2579
|
+
if (shouldSkipValidation) {
|
|
2580
|
+
if ((!hasNoValidationEffect || !_formState.isValid) &&
|
|
2581
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
|
|
2582
|
+
if (_options.mode === 'onBlur') {
|
|
2583
|
+
if (isBlurEvent) {
|
|
2584
|
+
_setValid();
|
|
2640
2585
|
}
|
|
2641
2586
|
}
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
for (const fieldName of _names.mount) {
|
|
2645
|
-
setValue(fieldName, get(values, fieldName));
|
|
2587
|
+
else if (!isBlurEvent) {
|
|
2588
|
+
_setValid();
|
|
2646
2589
|
}
|
|
2647
2590
|
}
|
|
2648
|
-
|
|
2649
|
-
|
|
2591
|
+
return (shouldRender &&
|
|
2592
|
+
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
|
|
2593
|
+
}
|
|
2594
|
+
if (!_options.resolver && props.validate) {
|
|
2595
|
+
await validateForm({
|
|
2596
|
+
name: name,
|
|
2597
|
+
eventType: event.type,
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
|
|
2601
|
+
if (_options.resolver) {
|
|
2602
|
+
const { errors } = await _runSchema([name]);
|
|
2603
|
+
_updateIsValidating([name]);
|
|
2604
|
+
_updateIsFieldValueUpdated(fieldValue);
|
|
2605
|
+
if (!isFieldValueUpdated) {
|
|
2606
|
+
!isEmptyObject(fieldState) && _subjects.state.next(fieldState);
|
|
2607
|
+
return;
|
|
2650
2608
|
}
|
|
2609
|
+
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
|
2610
|
+
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
|
2611
|
+
error = errorLookupResult.error;
|
|
2612
|
+
name = errorLookupResult.name;
|
|
2613
|
+
isValid = isEmptyObject(errors);
|
|
2651
2614
|
}
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2615
|
+
else {
|
|
2616
|
+
_updateIsValidating([name], true);
|
|
2617
|
+
error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
|
|
2618
|
+
_updateIsValidating([name]);
|
|
2619
|
+
_updateIsFieldValueUpdated(fieldValue);
|
|
2620
|
+
if (isFieldValueUpdated) {
|
|
2621
|
+
if (error) {
|
|
2622
|
+
isValid = false;
|
|
2623
|
+
}
|
|
2624
|
+
else if (_proxyFormState.isValid ||
|
|
2625
|
+
_proxySubscribeFormState.isValid) {
|
|
2626
|
+
isValid = await executeBuiltInValidation({
|
|
2627
|
+
fields: _fields,
|
|
2628
|
+
onlyCheckValid: true,
|
|
2629
|
+
name: name,
|
|
2630
|
+
eventType: event.type,
|
|
2631
|
+
});
|
|
2659
2632
|
}
|
|
2660
2633
|
}
|
|
2661
2634
|
}
|
|
2662
|
-
|
|
2663
|
-
|
|
2635
|
+
if (isFieldValueUpdated) {
|
|
2636
|
+
field._f.deps &&
|
|
2637
|
+
(!Array.isArray(field._f.deps) || field._f.deps.length > 0) &&
|
|
2638
|
+
trigger(field._f.deps);
|
|
2639
|
+
shouldRenderByError(name, isValid, error, fieldState);
|
|
2664
2640
|
}
|
|
2665
|
-
_subjects.array.next({
|
|
2666
|
-
values: { ...values },
|
|
2667
|
-
});
|
|
2668
|
-
_subjects.state.next({
|
|
2669
|
-
name: undefined,
|
|
2670
|
-
type: undefined,
|
|
2671
|
-
values: { ...values },
|
|
2672
|
-
});
|
|
2673
2641
|
}
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
disabled: new Set(),
|
|
2680
|
-
watch: new Set(),
|
|
2681
|
-
watchAll: false,
|
|
2682
|
-
focus: '',
|
|
2683
|
-
};
|
|
2684
|
-
_state.mount =
|
|
2685
|
-
!_proxyFormState.isValid ||
|
|
2686
|
-
!!keepStateOptions.keepIsValid ||
|
|
2687
|
-
!!keepStateOptions.keepDirtyValues ||
|
|
2688
|
-
(!_options.shouldUnregister && !isEmptyObject(values));
|
|
2689
|
-
_state.watch = !!_options.shouldUnregister;
|
|
2690
|
-
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
2691
|
-
_state.action = false;
|
|
2692
|
-
if (!keepStateOptions.keepErrors) {
|
|
2693
|
-
_formState.errors = {};
|
|
2642
|
+
};
|
|
2643
|
+
const _focusInput = (ref, key) => {
|
|
2644
|
+
if (get(_formState.errors, key) && ref.focus) {
|
|
2645
|
+
ref.focus();
|
|
2646
|
+
return 1;
|
|
2694
2647
|
}
|
|
2695
|
-
|
|
2696
|
-
submitCount: keepStateOptions.keepSubmitCount
|
|
2697
|
-
? _formState.submitCount
|
|
2698
|
-
: 0,
|
|
2699
|
-
isDirty: isEmptyResetValues
|
|
2700
|
-
? false
|
|
2701
|
-
: keepStateOptions.keepDirty
|
|
2702
|
-
? _formState.isDirty
|
|
2703
|
-
: keepStateOptions.keepValues
|
|
2704
|
-
? _getDirty()
|
|
2705
|
-
: !!(keepStateOptions.keepDefaultValues &&
|
|
2706
|
-
!deepEqual(formValues, _defaultValues)),
|
|
2707
|
-
isSubmitted: keepStateOptions.keepIsSubmitted
|
|
2708
|
-
? _formState.isSubmitted
|
|
2709
|
-
: false,
|
|
2710
|
-
dirtyFields: isEmptyResetValues
|
|
2711
|
-
? {}
|
|
2712
|
-
: keepStateOptions.keepDirtyValues
|
|
2713
|
-
? keepStateOptions.keepDefaultValues && _formValues
|
|
2714
|
-
? getDirtyFields(_defaultValues, _formValues)
|
|
2715
|
-
: _formState.dirtyFields
|
|
2716
|
-
: keepStateOptions.keepDefaultValues && formValues
|
|
2717
|
-
? getDirtyFields(_defaultValues, formValues)
|
|
2718
|
-
: keepStateOptions.keepDirty
|
|
2719
|
-
? _formState.dirtyFields
|
|
2720
|
-
: {},
|
|
2721
|
-
touchedFields: keepStateOptions.keepTouched
|
|
2722
|
-
? _formState.touchedFields
|
|
2723
|
-
: {},
|
|
2724
|
-
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
|
2725
|
-
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
|
2726
|
-
? _formState.isSubmitSuccessful
|
|
2727
|
-
: false,
|
|
2728
|
-
isSubmitting: false,
|
|
2729
|
-
defaultValues: _defaultValues,
|
|
2730
|
-
});
|
|
2648
|
+
return;
|
|
2731
2649
|
};
|
|
2732
|
-
const
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
?
|
|
2741
|
-
:
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2650
|
+
const trigger = async (name, options = {}) => {
|
|
2651
|
+
let isValid;
|
|
2652
|
+
let validationResult;
|
|
2653
|
+
const fieldNames = convertToArrayPayload(name);
|
|
2654
|
+
if (_options.resolver) {
|
|
2655
|
+
const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
|
|
2656
|
+
isValid = isEmptyObject(errors);
|
|
2657
|
+
validationResult = name
|
|
2658
|
+
? !fieldNames.some((name) => get(errors, name))
|
|
2659
|
+
: isValid;
|
|
2660
|
+
}
|
|
2661
|
+
else if (name) {
|
|
2662
|
+
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
|
|
2663
|
+
const field = get(_fields, fieldName);
|
|
2664
|
+
return await executeBuiltInValidation({
|
|
2665
|
+
fields: field && field._f ? { [fieldName]: field } : field,
|
|
2666
|
+
eventType: EVENTS.TRIGGER,
|
|
2748
2667
|
});
|
|
2749
|
-
}
|
|
2668
|
+
}))).every(Boolean);
|
|
2669
|
+
!(!validationResult && !_formState.isValid) && _setValid();
|
|
2750
2670
|
}
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
// its own.
|
|
2758
|
-
const { name, type, values, ...formState } = updatedFormState;
|
|
2759
|
-
_formState = {
|
|
2760
|
-
..._formState,
|
|
2761
|
-
...formState,
|
|
2762
|
-
};
|
|
2763
|
-
};
|
|
2764
|
-
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
|
2765
|
-
_options.defaultValues().then((values) => {
|
|
2766
|
-
reset(values, _options.resetOptions);
|
|
2767
|
-
_subjects.state.next({
|
|
2768
|
-
isLoading: false,
|
|
2769
|
-
});
|
|
2770
|
-
});
|
|
2771
|
-
const resetDefaultValues = (values, options = {}) => {
|
|
2772
|
-
_defaultValues = cloneObject(values);
|
|
2773
|
-
if (!options.keepDirty) {
|
|
2774
|
-
const newDirtyFields = getDirtyFields(_defaultValues, _formValues);
|
|
2775
|
-
_formState.dirtyFields = newDirtyFields;
|
|
2776
|
-
_formState.isDirty = !isEmptyObject(newDirtyFields);
|
|
2671
|
+
else {
|
|
2672
|
+
validationResult = isValid = await executeBuiltInValidation({
|
|
2673
|
+
fields: _fields,
|
|
2674
|
+
name,
|
|
2675
|
+
eventType: EVENTS.TRIGGER,
|
|
2676
|
+
});
|
|
2777
2677
|
}
|
|
2778
|
-
if (
|
|
2779
|
-
|
|
2678
|
+
if (options.delayError && _options.delayError && isString(name)) {
|
|
2679
|
+
const error = get(_formState.errors, name);
|
|
2680
|
+
if (error) {
|
|
2681
|
+
unset(_formState.errors, name);
|
|
2682
|
+
delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
|
|
2683
|
+
delayErrorCallbacks[name](_options.delayError);
|
|
2684
|
+
}
|
|
2685
|
+
else {
|
|
2686
|
+
clearTimeout(timers[name]);
|
|
2687
|
+
delete delayErrorCallbacks[name];
|
|
2688
|
+
}
|
|
2780
2689
|
}
|
|
2781
2690
|
_subjects.state.next({
|
|
2782
|
-
...
|
|
2783
|
-
|
|
2691
|
+
...(!isString(name) ||
|
|
2692
|
+
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
2693
|
+
isValid !== _formState.isValid)
|
|
2694
|
+
? {}
|
|
2695
|
+
: { name }),
|
|
2696
|
+
...(_options.resolver || !name ? { isValid } : {}),
|
|
2697
|
+
errors: _formState.errors,
|
|
2784
2698
|
});
|
|
2699
|
+
options.shouldFocus &&
|
|
2700
|
+
!validationResult &&
|
|
2701
|
+
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
|
2702
|
+
return validationResult;
|
|
2785
2703
|
};
|
|
2786
|
-
const
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
_getDirty,
|
|
2799
|
-
_setValid,
|
|
2800
|
-
_setFieldArray,
|
|
2801
|
-
_setDisabledField,
|
|
2802
|
-
_setErrors,
|
|
2803
|
-
_getFieldArray,
|
|
2804
|
-
_reset,
|
|
2805
|
-
_resetDefaultValues,
|
|
2806
|
-
_removeUnmounted,
|
|
2807
|
-
_disableForm,
|
|
2808
|
-
_subjects,
|
|
2809
|
-
_proxyFormState,
|
|
2810
|
-
get _fields() {
|
|
2811
|
-
return _fields;
|
|
2812
|
-
},
|
|
2813
|
-
get _formValues() {
|
|
2814
|
-
return _formValues;
|
|
2815
|
-
},
|
|
2816
|
-
get _state() {
|
|
2817
|
-
return _state;
|
|
2818
|
-
},
|
|
2819
|
-
set _state(value) {
|
|
2820
|
-
_state = value;
|
|
2821
|
-
},
|
|
2822
|
-
get _defaultValues() {
|
|
2823
|
-
return _defaultValues;
|
|
2824
|
-
},
|
|
2825
|
-
get _names() {
|
|
2826
|
-
return _names;
|
|
2827
|
-
},
|
|
2828
|
-
set _names(value) {
|
|
2829
|
-
_names = value;
|
|
2830
|
-
},
|
|
2831
|
-
get _formState() {
|
|
2832
|
-
return _formState;
|
|
2833
|
-
},
|
|
2834
|
-
get _options() {
|
|
2835
|
-
return _options;
|
|
2836
|
-
},
|
|
2837
|
-
set _options(value) {
|
|
2838
|
-
_options = {
|
|
2839
|
-
..._options,
|
|
2840
|
-
...value,
|
|
2841
|
-
};
|
|
2842
|
-
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
2843
|
-
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
2844
|
-
},
|
|
2845
|
-
},
|
|
2846
|
-
subscribe,
|
|
2847
|
-
trigger,
|
|
2848
|
-
register,
|
|
2849
|
-
handleSubmit,
|
|
2850
|
-
watch,
|
|
2851
|
-
setValue,
|
|
2852
|
-
setValues,
|
|
2853
|
-
getValues,
|
|
2854
|
-
reset,
|
|
2855
|
-
resetField,
|
|
2856
|
-
resetDefaultValues,
|
|
2857
|
-
clearErrors,
|
|
2858
|
-
unregister,
|
|
2859
|
-
setError,
|
|
2860
|
-
setFocus,
|
|
2861
|
-
getFieldState,
|
|
2862
|
-
};
|
|
2863
|
-
return {
|
|
2864
|
-
...methods,
|
|
2865
|
-
formControl: methods,
|
|
2704
|
+
const getValues = (fieldNames, config) => {
|
|
2705
|
+
let values = {
|
|
2706
|
+
...(_state.mount ? _formValues : _defaultValues),
|
|
2707
|
+
};
|
|
2708
|
+
if (config) {
|
|
2709
|
+
values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
|
|
2710
|
+
}
|
|
2711
|
+
return isUndefined(fieldNames)
|
|
2712
|
+
? values
|
|
2713
|
+
: isString(fieldNames)
|
|
2714
|
+
? get(values, fieldNames)
|
|
2715
|
+
: fieldNames.map((name) => get(values, name));
|
|
2866
2716
|
};
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
|
|
2874
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
2875
|
-
const r = ((Math.random() * 16 + d) % 16) | 0;
|
|
2876
|
-
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
2717
|
+
const getFieldState = (name, formState) => ({
|
|
2718
|
+
invalid: !!get((formState || _formState).errors, name),
|
|
2719
|
+
isDirty: !!get((formState || _formState).dirtyFields, name),
|
|
2720
|
+
error: get((formState || _formState).errors, name),
|
|
2721
|
+
isValidating: !!get(_formState.validatingFields, name),
|
|
2722
|
+
isTouched: !!get((formState || _formState).touchedFields, name),
|
|
2877
2723
|
});
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
...data.slice(0, index),
|
|
2895
|
-
...convertToArrayPayload(value),
|
|
2896
|
-
...data.slice(index),
|
|
2897
|
-
];
|
|
2898
|
-
}
|
|
2899
|
-
|
|
2900
|
-
var moveArrayAt = (data, from, to) => {
|
|
2901
|
-
if (!Array.isArray(data)) {
|
|
2902
|
-
return [];
|
|
2903
|
-
}
|
|
2904
|
-
if (isUndefined(data[to])) {
|
|
2905
|
-
data[to] = undefined;
|
|
2906
|
-
}
|
|
2907
|
-
data.splice(to, 0, data.splice(from, 1)[0]);
|
|
2908
|
-
return data;
|
|
2909
|
-
};
|
|
2910
|
-
|
|
2911
|
-
var prependAt = (data, value) => [
|
|
2912
|
-
...convertToArrayPayload(value),
|
|
2913
|
-
...convertToArrayPayload(data),
|
|
2914
|
-
];
|
|
2915
|
-
|
|
2916
|
-
function removeAtIndexes(data, indexes) {
|
|
2917
|
-
let i = 0;
|
|
2918
|
-
const temp = [...data];
|
|
2919
|
-
for (const index of indexes) {
|
|
2920
|
-
temp.splice(index - i, 1);
|
|
2921
|
-
i++;
|
|
2922
|
-
}
|
|
2923
|
-
return compact(temp).length ? temp : [];
|
|
2924
|
-
}
|
|
2925
|
-
var removeArrayAt = (data, index) => isUndefined(index)
|
|
2926
|
-
? []
|
|
2927
|
-
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
|
2928
|
-
|
|
2929
|
-
var swapArrayAt = (data, indexA, indexB) => {
|
|
2930
|
-
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
|
2931
|
-
};
|
|
2932
|
-
|
|
2933
|
-
var updateAt = (fieldValues, index, value) => {
|
|
2934
|
-
fieldValues[index] = value;
|
|
2935
|
-
return fieldValues;
|
|
2936
|
-
};
|
|
2937
|
-
|
|
2938
|
-
/**
|
|
2939
|
-
* 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)
|
|
2940
|
-
*
|
|
2941
|
-
* @remarks
|
|
2942
|
-
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
|
2943
|
-
*
|
|
2944
|
-
* @param props - useFieldArray props
|
|
2945
|
-
*
|
|
2946
|
-
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
|
2947
|
-
*
|
|
2948
|
-
* @example
|
|
2949
|
-
* ```tsx
|
|
2950
|
-
* function App() {
|
|
2951
|
-
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
|
2952
|
-
* defaultValues: {
|
|
2953
|
-
* test: []
|
|
2954
|
-
* }
|
|
2955
|
-
* });
|
|
2956
|
-
* const { fields, append } = useFieldArray({
|
|
2957
|
-
* control,
|
|
2958
|
-
* name: "test"
|
|
2959
|
-
* });
|
|
2960
|
-
*
|
|
2961
|
-
* return (
|
|
2962
|
-
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
|
2963
|
-
* {fields.map((item, index) => (
|
|
2964
|
-
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
|
2965
|
-
* ))}
|
|
2966
|
-
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
|
2967
|
-
* append
|
|
2968
|
-
* </button>
|
|
2969
|
-
* <input type="submit" />
|
|
2970
|
-
* </form>
|
|
2971
|
-
* );
|
|
2972
|
-
* }
|
|
2973
|
-
* ```
|
|
2974
|
-
*/
|
|
2975
|
-
function useFieldArray(props) {
|
|
2976
|
-
const formControl = useFormControlContext();
|
|
2977
|
-
const { control = formControl, name, keyName = 'id', disabled, shouldUnregister, rules, } = props;
|
|
2978
|
-
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
|
2979
|
-
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
|
2980
|
-
const _actioned = React.useRef(false);
|
|
2981
|
-
if (!disabled) {
|
|
2982
|
-
control._names.array.add(name);
|
|
2983
|
-
}
|
|
2984
|
-
React.useMemo(() => !disabled &&
|
|
2985
|
-
rules &&
|
|
2986
|
-
fields.length >= 0 &&
|
|
2987
|
-
control.register(name, rules), [control, name, fields.length, rules, disabled]);
|
|
2988
|
-
useIsomorphicLayoutEffect(() => {
|
|
2989
|
-
if (disabled) {
|
|
2990
|
-
return;
|
|
2724
|
+
const clearErrors = (name) => {
|
|
2725
|
+
const names = name ? convertToArrayPayload(name) : undefined;
|
|
2726
|
+
names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
|
|
2727
|
+
if (names) {
|
|
2728
|
+
names.forEach((inputName) => {
|
|
2729
|
+
_subjects.state.next({
|
|
2730
|
+
name: inputName,
|
|
2731
|
+
errors: _formState.errors,
|
|
2732
|
+
});
|
|
2733
|
+
});
|
|
2734
|
+
}
|
|
2735
|
+
else {
|
|
2736
|
+
_formState.errors = {};
|
|
2737
|
+
_subjects.state.next({
|
|
2738
|
+
errors: _formState.errors,
|
|
2739
|
+
});
|
|
2991
2740
|
}
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
2741
|
+
};
|
|
2742
|
+
const setError = (name, error, options) => {
|
|
2743
|
+
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
2744
|
+
const currentError = get(_formState.errors, name) || {};
|
|
2745
|
+
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
2746
|
+
set(_formState.errors, name, {
|
|
2747
|
+
...restOfErrorTree,
|
|
2748
|
+
...error,
|
|
2749
|
+
ref,
|
|
2750
|
+
});
|
|
2751
|
+
_subjects.state.next({
|
|
2752
|
+
name,
|
|
2753
|
+
errors: _formState.errors,
|
|
2754
|
+
isValid: false,
|
|
2755
|
+
});
|
|
2756
|
+
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
2757
|
+
};
|
|
2758
|
+
const watch = (name, defaultValue) => {
|
|
2759
|
+
if (isFunction(name)) {
|
|
2760
|
+
_valuesSubscriberCount++;
|
|
2761
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2762
|
+
next: (payload) => 'values' in payload &&
|
|
2763
|
+
name(payload.values || _getWatch(undefined, defaultValue), payload),
|
|
2764
|
+
});
|
|
2765
|
+
let called = false;
|
|
2766
|
+
return {
|
|
2767
|
+
unsubscribe: () => {
|
|
2768
|
+
if (called) {
|
|
2769
|
+
return;
|
|
3003
2770
|
}
|
|
2771
|
+
called = true;
|
|
2772
|
+
_valuesSubscriberCount--;
|
|
2773
|
+
unsubscribe();
|
|
2774
|
+
},
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
return _getWatch(name, defaultValue, true);
|
|
2778
|
+
};
|
|
2779
|
+
const _subscribe = (props) => {
|
|
2780
|
+
var _a;
|
|
2781
|
+
const needsValues = !!((_a = props.formState) === null || _a === void 0 ? void 0 : _a.values);
|
|
2782
|
+
if (needsValues) {
|
|
2783
|
+
_valuesSubscriberCount++;
|
|
2784
|
+
}
|
|
2785
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2786
|
+
next: (formState) => {
|
|
2787
|
+
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
2788
|
+
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
2789
|
+
const snapshot = { ..._formValues };
|
|
2790
|
+
props.callback({
|
|
2791
|
+
values: snapshot,
|
|
2792
|
+
..._formState,
|
|
2793
|
+
...formState,
|
|
2794
|
+
defaultValues: _defaultValues,
|
|
2795
|
+
});
|
|
3004
2796
|
}
|
|
3005
2797
|
},
|
|
3006
|
-
})
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
_actioned.current = true;
|
|
3010
|
-
control._setFieldArray(name, updatedFieldArrayValues);
|
|
3011
|
-
}, [control, name]);
|
|
3012
|
-
const append = (value, options) => {
|
|
3013
|
-
if (disabled) {
|
|
3014
|
-
return;
|
|
2798
|
+
});
|
|
2799
|
+
if (!needsValues) {
|
|
2800
|
+
return unsubscribe;
|
|
3015
2801
|
}
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
2802
|
+
let called = false;
|
|
2803
|
+
return () => {
|
|
2804
|
+
if (called) {
|
|
2805
|
+
return;
|
|
2806
|
+
}
|
|
2807
|
+
called = true;
|
|
2808
|
+
_valuesSubscriberCount--;
|
|
2809
|
+
unsubscribe();
|
|
2810
|
+
};
|
|
2811
|
+
};
|
|
2812
|
+
const subscribe = (props) => {
|
|
2813
|
+
_state.mount = true;
|
|
2814
|
+
_proxySubscribeFormState = {
|
|
2815
|
+
..._proxySubscribeFormState,
|
|
2816
|
+
...props.formState,
|
|
2817
|
+
};
|
|
2818
|
+
return _subscribe({
|
|
2819
|
+
...props,
|
|
2820
|
+
formState: {
|
|
2821
|
+
...defaultProxyFormState,
|
|
2822
|
+
...props.formState,
|
|
2823
|
+
},
|
|
3024
2824
|
});
|
|
3025
2825
|
};
|
|
3026
|
-
const
|
|
3027
|
-
|
|
3028
|
-
|
|
2826
|
+
const unregister = (name, options = {}) => {
|
|
2827
|
+
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
|
2828
|
+
_names.mount.delete(fieldName);
|
|
2829
|
+
_names.array.delete(fieldName);
|
|
2830
|
+
if (!options.keepValue) {
|
|
2831
|
+
unset(_fields, fieldName);
|
|
2832
|
+
unset(_formValues, fieldName);
|
|
2833
|
+
}
|
|
2834
|
+
!options.keepError && unset(_formState.errors, fieldName);
|
|
2835
|
+
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
|
2836
|
+
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
|
2837
|
+
!options.keepIsValidating &&
|
|
2838
|
+
unset(_formState.validatingFields, fieldName);
|
|
2839
|
+
!_options.shouldUnregister &&
|
|
2840
|
+
!options.keepDefaultValue &&
|
|
2841
|
+
unset(_defaultValues, fieldName);
|
|
3029
2842
|
}
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
|
|
3037
|
-
argA: fillEmptyArray(value),
|
|
2843
|
+
_subjects.state.next({
|
|
2844
|
+
values: cloneObject(_formValues),
|
|
2845
|
+
});
|
|
2846
|
+
_subjects.state.next({
|
|
2847
|
+
..._formState,
|
|
2848
|
+
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
|
3038
2849
|
});
|
|
2850
|
+
!options.keepIsValid && _setValid();
|
|
3039
2851
|
};
|
|
3040
|
-
const
|
|
3041
|
-
if (disabled)
|
|
3042
|
-
|
|
2852
|
+
const _setDisabledField = ({ disabled, name, }) => {
|
|
2853
|
+
if ((isBoolean(disabled) && _state.mount) ||
|
|
2854
|
+
!!disabled ||
|
|
2855
|
+
_names.disabled.has(name)) {
|
|
2856
|
+
const wasDisabled = _names.disabled.has(name);
|
|
2857
|
+
const isDisabled = !!disabled;
|
|
2858
|
+
const disabledStateChanged = wasDisabled !== isDisabled;
|
|
2859
|
+
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
|
2860
|
+
disabledStateChanged && _state.mount && !_state.action && _setValid();
|
|
2861
|
+
}
|
|
2862
|
+
};
|
|
2863
|
+
const register = (name, options = {}) => {
|
|
2864
|
+
let field = get(_fields, name);
|
|
2865
|
+
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
|
2866
|
+
const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
|
|
2867
|
+
set(_fields, name, {
|
|
2868
|
+
...(field || {}),
|
|
2869
|
+
_f: {
|
|
2870
|
+
...(field && field._f ? field._f : { ref: { name } }),
|
|
2871
|
+
name,
|
|
2872
|
+
mount: true,
|
|
2873
|
+
...options,
|
|
2874
|
+
},
|
|
2875
|
+
});
|
|
2876
|
+
_names.mount.add(name);
|
|
2877
|
+
if (field && !shouldRevalidateRemount) {
|
|
2878
|
+
_setDisabledField({
|
|
2879
|
+
disabled: isBoolean(options.disabled)
|
|
2880
|
+
? options.disabled
|
|
2881
|
+
: _options.disabled,
|
|
2882
|
+
name,
|
|
2883
|
+
});
|
|
2884
|
+
}
|
|
2885
|
+
else {
|
|
2886
|
+
updateValidAndValue(name, true, options.value);
|
|
2887
|
+
}
|
|
2888
|
+
return {
|
|
2889
|
+
...(disabledIsDefined
|
|
2890
|
+
? { disabled: options.disabled || _options.disabled }
|
|
2891
|
+
: {}),
|
|
2892
|
+
...(_options.progressive
|
|
2893
|
+
? {
|
|
2894
|
+
required: !!options.required,
|
|
2895
|
+
min: getRuleValue(options.min),
|
|
2896
|
+
max: getRuleValue(options.max),
|
|
2897
|
+
minLength: getRuleValue(options.minLength),
|
|
2898
|
+
maxLength: getRuleValue(options.maxLength),
|
|
2899
|
+
pattern: getRuleValue(options.pattern),
|
|
2900
|
+
}
|
|
2901
|
+
: {}),
|
|
2902
|
+
name,
|
|
2903
|
+
onChange,
|
|
2904
|
+
onBlur: onChange,
|
|
2905
|
+
ref: (ref) => {
|
|
2906
|
+
if (ref) {
|
|
2907
|
+
_names.registerName.add(name);
|
|
2908
|
+
register(name, options);
|
|
2909
|
+
_names.registerName.delete(name);
|
|
2910
|
+
field = get(_fields, name);
|
|
2911
|
+
const fieldRef = isUndefined(ref.value)
|
|
2912
|
+
? ref.querySelectorAll
|
|
2913
|
+
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
|
2914
|
+
: ref
|
|
2915
|
+
: ref;
|
|
2916
|
+
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
|
2917
|
+
const refs = field._f.refs || [];
|
|
2918
|
+
if (radioOrCheckbox
|
|
2919
|
+
? refs.find((option) => option === fieldRef)
|
|
2920
|
+
: fieldRef === field._f.ref) {
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2923
|
+
const newField = {
|
|
2924
|
+
...field._f,
|
|
2925
|
+
};
|
|
2926
|
+
if (radioOrCheckbox) {
|
|
2927
|
+
newField.refs = [
|
|
2928
|
+
...refs.filter(live),
|
|
2929
|
+
fieldRef,
|
|
2930
|
+
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
|
2931
|
+
];
|
|
2932
|
+
newField.ref = { type: fieldRef.type, name };
|
|
2933
|
+
}
|
|
2934
|
+
else {
|
|
2935
|
+
newField.ref = fieldRef;
|
|
2936
|
+
delete newField.refs;
|
|
2937
|
+
}
|
|
2938
|
+
set(_fields, name, {
|
|
2939
|
+
_f: newField,
|
|
2940
|
+
});
|
|
2941
|
+
updateValidAndValue(name, false, undefined, fieldRef);
|
|
2942
|
+
}
|
|
2943
|
+
else {
|
|
2944
|
+
field = get(_fields, name, {});
|
|
2945
|
+
if (field._f) {
|
|
2946
|
+
field._f.mount = false;
|
|
2947
|
+
}
|
|
2948
|
+
(_options.shouldUnregister || options.shouldUnregister) &&
|
|
2949
|
+
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
|
2950
|
+
_names.unMount.add(name);
|
|
2951
|
+
}
|
|
2952
|
+
},
|
|
2953
|
+
};
|
|
2954
|
+
};
|
|
2955
|
+
const _focusError = () => _options.shouldFocusError &&
|
|
2956
|
+
!_options.shouldUseNativeValidation &&
|
|
2957
|
+
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
|
2958
|
+
const _disableForm = (disabled) => {
|
|
2959
|
+
if (isBoolean(disabled)) {
|
|
2960
|
+
_subjects.state.next({ disabled });
|
|
2961
|
+
iterateFieldsByAction(_fields, (ref, name) => {
|
|
2962
|
+
const currentField = get(_fields, name);
|
|
2963
|
+
if (currentField) {
|
|
2964
|
+
ref.disabled = currentField._f.disabled || disabled;
|
|
2965
|
+
if (Array.isArray(currentField._f.refs)) {
|
|
2966
|
+
currentField._f.refs.forEach((inputRef) => {
|
|
2967
|
+
inputRef.disabled = currentField._f.disabled || disabled;
|
|
2968
|
+
});
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
}, 0, false);
|
|
3043
2972
|
}
|
|
3044
|
-
const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
|
|
3045
|
-
ids.current = removeArrayAt(ids.current, index);
|
|
3046
|
-
updateValues(updatedFieldArrayValues);
|
|
3047
|
-
setFields(updatedFieldArrayValues);
|
|
3048
|
-
!Array.isArray(get(control._fields, name)) &&
|
|
3049
|
-
set(control._fields, name, undefined);
|
|
3050
|
-
control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
|
|
3051
|
-
argA: index,
|
|
3052
|
-
});
|
|
3053
2973
|
};
|
|
3054
|
-
const
|
|
3055
|
-
|
|
3056
|
-
|
|
2974
|
+
const handleSubmit = (onValid, onInvalid) => async (e) => {
|
|
2975
|
+
let onValidError = undefined;
|
|
2976
|
+
if (e) {
|
|
2977
|
+
e.preventDefault && e.preventDefault();
|
|
2978
|
+
e.persist &&
|
|
2979
|
+
e.persist();
|
|
3057
2980
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
ids.current = insert(ids.current, index, insertValue.map(generateId));
|
|
3062
|
-
updateValues(updatedFieldArrayValues);
|
|
3063
|
-
setFields(updatedFieldArrayValues);
|
|
3064
|
-
control._setFieldArray(name, updatedFieldArrayValues, insert, {
|
|
3065
|
-
argA: index,
|
|
3066
|
-
argB: fillEmptyArray(value),
|
|
2981
|
+
let fieldValues = cloneObject(_formValues);
|
|
2982
|
+
_subjects.state.next({
|
|
2983
|
+
isSubmitting: true,
|
|
3067
2984
|
});
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
2985
|
+
if (_options.resolver) {
|
|
2986
|
+
const { errors, values } = await _runSchema();
|
|
2987
|
+
_updateIsValidating();
|
|
2988
|
+
_formState.errors = errors;
|
|
2989
|
+
fieldValues = cloneObject(values);
|
|
3072
2990
|
}
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
|
|
3079
|
-
argA: indexA,
|
|
3080
|
-
argB: indexB,
|
|
3081
|
-
}, false);
|
|
3082
|
-
};
|
|
3083
|
-
const move = (from, to) => {
|
|
3084
|
-
if (disabled) {
|
|
3085
|
-
return;
|
|
2991
|
+
else {
|
|
2992
|
+
await executeBuiltInValidation({
|
|
2993
|
+
fields: _fields,
|
|
2994
|
+
eventType: EVENTS.SUBMIT,
|
|
2995
|
+
});
|
|
3086
2996
|
}
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
2997
|
+
if (_names.disabled.size) {
|
|
2998
|
+
for (const name of _names.disabled) {
|
|
2999
|
+
unset(fieldValues, name);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
unset(_formState.errors, ROOT_ERROR_TYPE);
|
|
3003
|
+
if (isEmptyObject(_formState.errors)) {
|
|
3004
|
+
_subjects.state.next({
|
|
3005
|
+
errors: {},
|
|
3006
|
+
});
|
|
3007
|
+
try {
|
|
3008
|
+
await onValid(fieldValues, e);
|
|
3009
|
+
}
|
|
3010
|
+
catch (error) {
|
|
3011
|
+
onValidError = error;
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
else {
|
|
3015
|
+
if (onInvalid) {
|
|
3016
|
+
await onInvalid({ ..._formState.errors }, e);
|
|
3017
|
+
}
|
|
3018
|
+
_focusError();
|
|
3019
|
+
setTimeout(_focusError);
|
|
3020
|
+
}
|
|
3021
|
+
_subjects.state.next({
|
|
3022
|
+
isSubmitted: true,
|
|
3023
|
+
isSubmitting: false,
|
|
3024
|
+
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
|
3025
|
+
submitCount: _formState.submitCount + 1,
|
|
3026
|
+
errors: _formState.errors,
|
|
3027
|
+
});
|
|
3028
|
+
if (onValidError) {
|
|
3029
|
+
throw onValidError;
|
|
3100
3030
|
}
|
|
3101
|
-
const updateValue = cloneObject(value);
|
|
3102
|
-
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
|
|
3103
|
-
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
|
3104
|
-
updateValues(updatedFieldArrayValues);
|
|
3105
|
-
setFields([...updatedFieldArrayValues]);
|
|
3106
|
-
control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
|
|
3107
|
-
argA: index,
|
|
3108
|
-
argB: updateValue,
|
|
3109
|
-
}, true, false);
|
|
3110
3031
|
};
|
|
3111
|
-
const
|
|
3112
|
-
if (
|
|
3113
|
-
|
|
3032
|
+
const resetField = (name, options = {}) => {
|
|
3033
|
+
if (get(_fields, name)) {
|
|
3034
|
+
if (isUndefined(options.defaultValue)) {
|
|
3035
|
+
setValue(name, cloneObject(get(_defaultValues, name)));
|
|
3036
|
+
}
|
|
3037
|
+
else {
|
|
3038
|
+
setValue(name, options.defaultValue);
|
|
3039
|
+
set(_defaultValues, name, cloneObject(options.defaultValue));
|
|
3040
|
+
}
|
|
3041
|
+
if (!options.keepTouched) {
|
|
3042
|
+
unset(_formState.touchedFields, name);
|
|
3043
|
+
}
|
|
3044
|
+
if (!options.keepDirty) {
|
|
3045
|
+
unset(_formState.dirtyFields, name);
|
|
3046
|
+
_formState.isDirty = options.defaultValue
|
|
3047
|
+
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
|
3048
|
+
: _getDirty();
|
|
3049
|
+
}
|
|
3050
|
+
if (!options.keepError) {
|
|
3051
|
+
unset(_formState.errors, name);
|
|
3052
|
+
_proxyFormState.isValid && _setValid();
|
|
3053
|
+
}
|
|
3054
|
+
_subjects.state.next({ ..._formState });
|
|
3114
3055
|
}
|
|
3115
|
-
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
|
|
3116
|
-
ids.current = updatedFieldArrayValues.map(generateId);
|
|
3117
|
-
updateValues([...updatedFieldArrayValues]);
|
|
3118
|
-
setFields([...updatedFieldArrayValues]);
|
|
3119
|
-
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
|
3120
3056
|
};
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3057
|
+
const _reset = (formValues, keepStateOptions = {}) => {
|
|
3058
|
+
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
|
|
3059
|
+
const cloneUpdatedValues = cloneObject(updatedValues);
|
|
3060
|
+
const isEmptyResetValues = isEmptyObject(formValues);
|
|
3061
|
+
const values = cloneUpdatedValues;
|
|
3062
|
+
const fieldRefs = _fields;
|
|
3063
|
+
if (!keepStateOptions.keepDefaultValues) {
|
|
3064
|
+
_defaultValues = updatedValues;
|
|
3124
3065
|
}
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
var _a, _b;
|
|
3138
|
-
control._updateIsValidating([name]);
|
|
3139
|
-
const error = get(result.errors, name);
|
|
3140
|
-
const existingError = get(control._formState.errors, name);
|
|
3141
|
-
const existingErrorType = existingError && (existingError.type || ((_a = existingError.root) === null || _a === void 0 ? void 0 : _a.type));
|
|
3142
|
-
const existingErrorMessage = existingError &&
|
|
3143
|
-
(existingError.message || ((_b = existingError.root) === null || _b === void 0 ? void 0 : _b.message));
|
|
3144
|
-
if (existingError
|
|
3145
|
-
? (!error && existingErrorType) ||
|
|
3146
|
-
(error &&
|
|
3147
|
-
(existingErrorType !== error.type ||
|
|
3148
|
-
existingErrorMessage !== error.message))
|
|
3149
|
-
: error && error.type) {
|
|
3150
|
-
if (error) {
|
|
3151
|
-
isObject(error) &&
|
|
3152
|
-
!Object.keys(error).some((key) => !Number.isNaN(+key))
|
|
3153
|
-
? updateFieldArrayRootError(control._formState.errors, { [name]: error }, name)
|
|
3154
|
-
: set(control._formState.errors, name, error);
|
|
3155
|
-
}
|
|
3156
|
-
else {
|
|
3157
|
-
unset(control._formState.errors, name);
|
|
3158
|
-
}
|
|
3159
|
-
control._subjects.state.next({
|
|
3160
|
-
errors: control._formState.errors,
|
|
3161
|
-
});
|
|
3066
|
+
if (!keepStateOptions.keepValues) {
|
|
3067
|
+
if (keepStateOptions.keepDirtyValues) {
|
|
3068
|
+
const fieldsToCheck = new Set([
|
|
3069
|
+
..._names.mount,
|
|
3070
|
+
...Object.keys(getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)),
|
|
3071
|
+
]);
|
|
3072
|
+
for (const fieldName of Array.from(fieldsToCheck)) {
|
|
3073
|
+
const isDirty = get(_formState.dirtyFields, fieldName);
|
|
3074
|
+
const existingValue = get(_formValues, fieldName);
|
|
3075
|
+
const newValue = get(values, fieldName);
|
|
3076
|
+
if (isDirty && !isUndefined(existingValue)) {
|
|
3077
|
+
set(values, fieldName, existingValue);
|
|
3162
3078
|
}
|
|
3163
|
-
|
|
3079
|
+
else if (!isDirty && !isUndefined(newValue)) {
|
|
3080
|
+
setValue(fieldName, newValue);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3164
3083
|
}
|
|
3165
3084
|
else {
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3085
|
+
if (isWeb && isUndefined(formValues)) {
|
|
3086
|
+
for (const name of _names.mount) {
|
|
3087
|
+
const field = get(_fields, name);
|
|
3088
|
+
if (field && field._f) {
|
|
3089
|
+
const fieldReference = Array.isArray(field._f.refs)
|
|
3090
|
+
? field._f.refs[0]
|
|
3091
|
+
: field._f.ref;
|
|
3092
|
+
if (isHTMLElement(fieldReference)) {
|
|
3093
|
+
const form = fieldReference.closest('form');
|
|
3094
|
+
if (form) {
|
|
3095
|
+
form.reset();
|
|
3096
|
+
break;
|
|
3097
|
+
}
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3175
3101
|
}
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
name,
|
|
3184
|
-
values: cloneObject(control._formValues),
|
|
3185
|
-
});
|
|
3186
|
-
control._names.focus &&
|
|
3187
|
-
iterateFieldsByAction(control._fields, (ref, key) => {
|
|
3188
|
-
if (control._names.focus &&
|
|
3189
|
-
key.startsWith(control._names.focus) &&
|
|
3190
|
-
ref.focus) {
|
|
3191
|
-
ref.focus();
|
|
3192
|
-
return 1;
|
|
3102
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
3103
|
+
for (const fieldName of _names.mount) {
|
|
3104
|
+
setValue(fieldName, get(values, fieldName));
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
else {
|
|
3108
|
+
_fields = {};
|
|
3193
3109
|
}
|
|
3194
|
-
return;
|
|
3195
|
-
});
|
|
3196
|
-
control._names.focus = '';
|
|
3197
|
-
control._setValid();
|
|
3198
|
-
_actioned.current = false;
|
|
3199
|
-
}, [fields, name, control, disabled]);
|
|
3200
|
-
React.useEffect(() => {
|
|
3201
|
-
if (!disabled) {
|
|
3202
|
-
!get(control._formValues, name) && control._setFieldArray(name);
|
|
3203
|
-
}
|
|
3204
|
-
return () => {
|
|
3205
|
-
if (disabled) {
|
|
3206
|
-
return;
|
|
3207
3110
|
}
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3111
|
+
if (_options.shouldUnregister) {
|
|
3112
|
+
_formValues = keepStateOptions.keepDefaultValues
|
|
3113
|
+
? cloneObject(_defaultValues)
|
|
3114
|
+
: {};
|
|
3115
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
3116
|
+
for (const fieldName of _names.mount) {
|
|
3117
|
+
set(_formValues, fieldName, get(values, fieldName));
|
|
3118
|
+
}
|
|
3213
3119
|
}
|
|
3214
|
-
}
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3120
|
+
}
|
|
3121
|
+
else {
|
|
3122
|
+
_formValues = cloneObject(values);
|
|
3123
|
+
}
|
|
3124
|
+
_subjects.array.next({
|
|
3125
|
+
values: { ...values },
|
|
3126
|
+
});
|
|
3127
|
+
_subjects.state.next({
|
|
3128
|
+
name: undefined,
|
|
3129
|
+
type: undefined,
|
|
3130
|
+
values: { ...values },
|
|
3131
|
+
});
|
|
3132
|
+
}
|
|
3133
|
+
_names = {
|
|
3134
|
+
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
|
|
3135
|
+
unMount: new Set(),
|
|
3136
|
+
array: new Set(),
|
|
3137
|
+
registerName: new Set(),
|
|
3138
|
+
disabled: new Set(),
|
|
3139
|
+
watch: new Set(),
|
|
3140
|
+
watchAll: false,
|
|
3141
|
+
focus: '',
|
|
3142
|
+
};
|
|
3143
|
+
_state.mount =
|
|
3144
|
+
!_proxyFormState.isValid ||
|
|
3145
|
+
!!keepStateOptions.keepIsValid ||
|
|
3146
|
+
!!keepStateOptions.keepDirtyValues ||
|
|
3147
|
+
(!_options.shouldUnregister && !isEmptyObject(values));
|
|
3148
|
+
_state.watch = !!_options.shouldUnregister;
|
|
3149
|
+
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
3150
|
+
_state.action = false;
|
|
3151
|
+
if (!keepStateOptions.keepErrors) {
|
|
3152
|
+
_formState.errors = {};
|
|
3153
|
+
}
|
|
3154
|
+
_subjects.state.next({
|
|
3155
|
+
submitCount: keepStateOptions.keepSubmitCount
|
|
3156
|
+
? _formState.submitCount
|
|
3157
|
+
: 0,
|
|
3158
|
+
isDirty: isEmptyResetValues
|
|
3159
|
+
? false
|
|
3160
|
+
: keepStateOptions.keepDirty
|
|
3161
|
+
? _formState.isDirty
|
|
3162
|
+
: keepStateOptions.keepValues
|
|
3163
|
+
? _getDirty()
|
|
3164
|
+
: !!(keepStateOptions.keepDefaultValues &&
|
|
3165
|
+
!deepEqual(formValues, _defaultValues)),
|
|
3166
|
+
isSubmitted: keepStateOptions.keepIsSubmitted
|
|
3167
|
+
? _formState.isSubmitted
|
|
3168
|
+
: false,
|
|
3169
|
+
dirtyFields: isEmptyResetValues
|
|
3170
|
+
? {}
|
|
3171
|
+
: keepStateOptions.keepDirtyValues
|
|
3172
|
+
? keepStateOptions.keepDefaultValues && _formValues
|
|
3173
|
+
? getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)
|
|
3174
|
+
: _formState.dirtyFields
|
|
3175
|
+
: keepStateOptions.keepDefaultValues && formValues
|
|
3176
|
+
? getDirtyFields(_defaultValues, formValues, undefined, fieldRefs)
|
|
3177
|
+
: keepStateOptions.keepDirty
|
|
3178
|
+
? _formState.dirtyFields
|
|
3179
|
+
: {},
|
|
3180
|
+
touchedFields: keepStateOptions.keepTouched
|
|
3181
|
+
? _formState.touchedFields
|
|
3182
|
+
: {},
|
|
3183
|
+
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
|
3184
|
+
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
|
3185
|
+
? _formState.isSubmitSuccessful
|
|
3186
|
+
: false,
|
|
3187
|
+
isSubmitting: false,
|
|
3188
|
+
defaultValues: _defaultValues,
|
|
3189
|
+
});
|
|
3190
|
+
};
|
|
3191
|
+
const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
|
|
3192
|
+
? formValues(_formValues)
|
|
3193
|
+
: formValues, { ..._options.resetOptions, ...keepStateOptions });
|
|
3194
|
+
const setFocus = (name, options = {}) => {
|
|
3195
|
+
const field = get(_fields, name);
|
|
3196
|
+
const fieldReference = field && field._f;
|
|
3197
|
+
if (fieldReference) {
|
|
3198
|
+
const fieldRef = fieldReference.refs
|
|
3199
|
+
? fieldReference.refs[0]
|
|
3200
|
+
: fieldReference.ref;
|
|
3201
|
+
if (fieldRef.focus) {
|
|
3202
|
+
setTimeout(() => {
|
|
3203
|
+
fieldRef.focus();
|
|
3204
|
+
options.shouldSelect &&
|
|
3205
|
+
isFunction(fieldRef.select) &&
|
|
3206
|
+
fieldRef.select();
|
|
3219
3207
|
});
|
|
3220
3208
|
}
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3211
|
+
const _setFormState = (updatedFormState) => {
|
|
3212
|
+
// `name`, `type`, and `values` describe the event that produced this
|
|
3213
|
+
// update, not the form's persisted state (they aren't part of
|
|
3214
|
+
// `FormState`). Merging them in would leak a stale `name`/`type` from
|
|
3215
|
+
// one event into a later, unrelated notification that doesn't specify
|
|
3216
|
+
// its own.
|
|
3217
|
+
const { name, type, values, ...formState } = updatedFormState;
|
|
3218
|
+
_formState = {
|
|
3219
|
+
..._formState,
|
|
3220
|
+
...formState,
|
|
3224
3221
|
};
|
|
3225
|
-
}
|
|
3222
|
+
};
|
|
3223
|
+
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
|
3224
|
+
_options.defaultValues().then((values) => {
|
|
3225
|
+
reset(values, _options.resetOptions);
|
|
3226
|
+
_subjects.state.next({
|
|
3227
|
+
isLoading: false,
|
|
3228
|
+
});
|
|
3229
|
+
});
|
|
3230
|
+
const resetDefaultValues = (values, options = {}) => {
|
|
3231
|
+
_defaultValues = cloneObject(values);
|
|
3232
|
+
if (!options.keepDirty) {
|
|
3233
|
+
const newDirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
3234
|
+
_formState.dirtyFields = newDirtyFields;
|
|
3235
|
+
_formState.isDirty = !isEmptyObject(newDirtyFields);
|
|
3236
|
+
}
|
|
3237
|
+
if (!options.keepIsValid) {
|
|
3238
|
+
_setValid();
|
|
3239
|
+
}
|
|
3240
|
+
_subjects.state.next({
|
|
3241
|
+
..._formState,
|
|
3242
|
+
defaultValues: _defaultValues,
|
|
3243
|
+
});
|
|
3244
|
+
};
|
|
3245
|
+
const methods = {
|
|
3246
|
+
control: {
|
|
3247
|
+
register,
|
|
3248
|
+
unregister,
|
|
3249
|
+
getFieldState,
|
|
3250
|
+
handleSubmit,
|
|
3251
|
+
setError,
|
|
3252
|
+
_subscribe,
|
|
3253
|
+
_runSchema,
|
|
3254
|
+
_updateIsValidating,
|
|
3255
|
+
_focusError,
|
|
3256
|
+
_getWatch,
|
|
3257
|
+
_getDirty,
|
|
3258
|
+
_setValid,
|
|
3259
|
+
_setFieldArray,
|
|
3260
|
+
_setDisabledField,
|
|
3261
|
+
_setErrors,
|
|
3262
|
+
_getFieldArray,
|
|
3263
|
+
_reset,
|
|
3264
|
+
_resetDefaultValues,
|
|
3265
|
+
_removeUnmounted,
|
|
3266
|
+
_disableForm,
|
|
3267
|
+
_subjects,
|
|
3268
|
+
_proxyFormState,
|
|
3269
|
+
get _fields() {
|
|
3270
|
+
return _fields;
|
|
3271
|
+
},
|
|
3272
|
+
get _formValues() {
|
|
3273
|
+
return _formValues;
|
|
3274
|
+
},
|
|
3275
|
+
get _state() {
|
|
3276
|
+
return _state;
|
|
3277
|
+
},
|
|
3278
|
+
set _state(value) {
|
|
3279
|
+
_state = value;
|
|
3280
|
+
},
|
|
3281
|
+
get _defaultValues() {
|
|
3282
|
+
return _defaultValues;
|
|
3283
|
+
},
|
|
3284
|
+
get _names() {
|
|
3285
|
+
return _names;
|
|
3286
|
+
},
|
|
3287
|
+
set _names(value) {
|
|
3288
|
+
_names = value;
|
|
3289
|
+
},
|
|
3290
|
+
get _formState() {
|
|
3291
|
+
return _formState;
|
|
3292
|
+
},
|
|
3293
|
+
get _options() {
|
|
3294
|
+
return _options;
|
|
3295
|
+
},
|
|
3296
|
+
set _options(value) {
|
|
3297
|
+
_options = {
|
|
3298
|
+
..._options,
|
|
3299
|
+
...value,
|
|
3300
|
+
};
|
|
3301
|
+
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
3302
|
+
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
3303
|
+
},
|
|
3304
|
+
},
|
|
3305
|
+
subscribe,
|
|
3306
|
+
trigger,
|
|
3307
|
+
register,
|
|
3308
|
+
handleSubmit,
|
|
3309
|
+
watch,
|
|
3310
|
+
setValue,
|
|
3311
|
+
setValues,
|
|
3312
|
+
getValues,
|
|
3313
|
+
reset,
|
|
3314
|
+
resetField,
|
|
3315
|
+
resetDefaultValues,
|
|
3316
|
+
clearErrors,
|
|
3317
|
+
unregister,
|
|
3318
|
+
setError,
|
|
3319
|
+
setFocus,
|
|
3320
|
+
getFieldState,
|
|
3321
|
+
};
|
|
3226
3322
|
return {
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
prepend: React.useCallback(prepend, [
|
|
3230
|
-
updateValues,
|
|
3231
|
-
name,
|
|
3232
|
-
control,
|
|
3233
|
-
disabled,
|
|
3234
|
-
]),
|
|
3235
|
-
append: React.useCallback(append, [updateValues, name, control, disabled]),
|
|
3236
|
-
remove: React.useCallback(remove, [updateValues, name, control, disabled]),
|
|
3237
|
-
insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
|
|
3238
|
-
update: React.useCallback(update, [updateValues, name, control, disabled]),
|
|
3239
|
-
replace: React.useCallback(replace, [
|
|
3240
|
-
updateValues,
|
|
3241
|
-
name,
|
|
3242
|
-
control,
|
|
3243
|
-
disabled,
|
|
3244
|
-
]),
|
|
3245
|
-
fields: React.useMemo(() => fields.map((field, index) => ({
|
|
3246
|
-
...field,
|
|
3247
|
-
...(isBoolean(disabled) ? { disabled } : {}),
|
|
3248
|
-
[keyName]: ids.current[index] || generateId(),
|
|
3249
|
-
})), [fields, keyName, disabled]),
|
|
3323
|
+
...methods,
|
|
3324
|
+
formControl: methods,
|
|
3250
3325
|
};
|
|
3251
3326
|
}
|
|
3252
3327
|
|
|
@@ -3421,5 +3496,5 @@ function useForm(props = {}) {
|
|
|
3421
3496
|
*/
|
|
3422
3497
|
const Watch = (props) => props.render(useWatch({ name: props.names, ...props }));
|
|
3423
3498
|
|
|
3424
|
-
export { Controller, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
|
3499
|
+
export { Controller, FieldArray, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
|
3425
3500
|
//# sourceMappingURL=index.esm.mjs.map
|