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