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