react-hook-form 7.17.0 → 7.17.4
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/CHANGELOG.md +1185 -0
- package/README.md +24 -0
- package/dist/controller.d.ts +2 -2
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +447 -446
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/shouldSubscribeByName.d.ts +2 -0
- package/dist/types/controller.d.ts +15 -18
- package/dist/types/fields.d.ts +2 -2
- package/dist/types/form.d.ts +9 -10
- package/dist/types/utils.d.ts +21 -11
- package/dist/useController.d.ts +2 -2
- package/dist/useSubscribe.d.ts +4 -3
- package/dist/useWatch.d.ts +4 -4
- package/dist/utils/cloneObject.d.ts +1 -1
- package/dist/utils/convertToArrayPayload.d.ts +1 -1
- package/dist/utils/get.d.ts +1 -1
- package/dist/utils/{Subject.d.ts → subject.d.ts} +3 -2
- package/package.json +17 -19
package/dist/index.esm.js
CHANGED
@@ -65,10 +65,9 @@ var omit = (source, key) => {
|
|
65
65
|
return copy;
|
66
66
|
};
|
67
67
|
|
68
|
-
const
|
69
|
-
|
70
|
-
const
|
71
|
-
const FormProvider = (props) => (React.createElement(FormContext.Provider, { value: omit(props, 'children') }, props.children));
|
68
|
+
const HookFormContext = React.createContext(null);
|
69
|
+
const useFormContext = () => React.useContext(HookFormContext);
|
70
|
+
const FormProvider = (props) => (React.createElement(HookFormContext.Provider, { value: omit(props, 'children') }, props.children));
|
72
71
|
|
73
72
|
var getProxyFormState = (formState, _proxyFormState, localProxyFormState, isRoot = true) => {
|
74
73
|
function createGetter(prop) {
|
@@ -102,29 +101,41 @@ var shouldRenderFormState = (formStateData, _proxyFormState, isRoot) => {
|
|
102
101
|
(!isRoot || VALIDATION_MODE.all)));
|
103
102
|
};
|
104
103
|
|
105
|
-
var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
|
104
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
106
105
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
106
|
+
var shouldSubscribeByName = (name, signalName) => !name ||
|
107
|
+
!signalName ||
|
108
|
+
convertToArrayPayload(name).some((currentName) => currentName &&
|
109
|
+
(currentName.startsWith(signalName) ||
|
110
|
+
signalName.startsWith(currentName)));
|
111
|
+
|
112
|
+
const tearDown = (_unsubscribe) => {
|
113
|
+
if (_unsubscribe.current) {
|
114
|
+
_unsubscribe.current.unsubscribe();
|
115
|
+
_unsubscribe.current = undefined;
|
115
116
|
}
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
if (!_unSubscribe.current && _subscription.current) {
|
121
|
-
_unSubscribe.current = _subscription.current.subscribe({
|
122
|
-
next: callback,
|
123
|
-
});
|
124
|
-
}
|
117
|
+
};
|
118
|
+
const updateSubscriptionProps = ({ _unsubscribe, props }) => () => {
|
119
|
+
if (props.disabled) {
|
120
|
+
tearDown(_unsubscribe);
|
125
121
|
}
|
126
|
-
|
127
|
-
|
122
|
+
else if (!_unsubscribe.current) {
|
123
|
+
_unsubscribe.current = props.subject.subscribe({
|
124
|
+
next: props.callback,
|
125
|
+
});
|
126
|
+
}
|
127
|
+
};
|
128
|
+
function useSubscribe(props) {
|
129
|
+
const _unsubscribe = React.useRef();
|
130
|
+
const _updateSubscription = React.useRef(() => { });
|
131
|
+
_updateSubscription.current = updateSubscriptionProps({
|
132
|
+
_unsubscribe,
|
133
|
+
props,
|
134
|
+
});
|
135
|
+
!props.skipEarlySubscription && _updateSubscription.current();
|
136
|
+
React.useEffect(() => {
|
137
|
+
_updateSubscription.current();
|
138
|
+
return () => tearDown(_unsubscribe);
|
128
139
|
}, []);
|
129
140
|
}
|
130
141
|
|
@@ -144,9 +155,7 @@ function useFormState(props) {
|
|
144
155
|
_name.current = name;
|
145
156
|
useSubscribe({
|
146
157
|
disabled,
|
147
|
-
callback: (formState) => (
|
148
|
-
!formState.name ||
|
149
|
-
convertToArrayPayload(_name.current).includes(formState.name)) &&
|
158
|
+
callback: (formState) => shouldSubscribeByName(_name.current, formState.name) &&
|
150
159
|
shouldRenderFormState(formState, _localProxyFormState.current) &&
|
151
160
|
updateFormState(Object.assign(Object.assign({}, control._formState), formState)),
|
152
161
|
subject: control._subjects.state,
|
@@ -167,7 +176,7 @@ function useController(props) {
|
|
167
176
|
useSubscribe({
|
168
177
|
subject: control._subjects.control,
|
169
178
|
callback: (data) => (!data.name || _name.current === data.name) &&
|
170
|
-
setInputStateValue(get(data.values,
|
179
|
+
setInputStateValue(get(data.values, _name.current)),
|
171
180
|
});
|
172
181
|
const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
|
173
182
|
const updateMounted = React.useCallback((name, value) => {
|
@@ -179,7 +188,7 @@ function useController(props) {
|
|
179
188
|
React.useEffect(() => {
|
180
189
|
updateMounted(name, true);
|
181
190
|
return () => {
|
182
|
-
const _shouldUnregisterField = control.
|
191
|
+
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
183
192
|
if (isNameInFieldArray(control._names.array, name)
|
184
193
|
? _shouldUnregisterField && !control._stateFlags.action
|
185
194
|
: _shouldUnregisterField) {
|
@@ -334,7 +343,7 @@ var moveArrayAt = (data, from, to) => {
|
|
334
343
|
return [];
|
335
344
|
};
|
336
345
|
|
337
|
-
var
|
346
|
+
var omitKeys = (fields, keyName) => fields.map((field = {}) => omit(field, keyName));
|
338
347
|
|
339
348
|
function prepend(data, value) {
|
340
349
|
return [...convertToArrayPayload(value), ...convertToArrayPayload(data)];
|
@@ -365,81 +374,84 @@ var updateAt = (fieldValues, index, value) => {
|
|
365
374
|
const useFieldArray = (props) => {
|
366
375
|
const methods = useFormContext();
|
367
376
|
const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
|
368
|
-
const [fields, setFields] = React.useState(mapIds(control.
|
377
|
+
const [fields, setFields] = React.useState(mapIds(control._getFieldArray(name), keyName));
|
369
378
|
const _fieldIds = React.useRef(fields);
|
379
|
+
const _name = React.useRef(name);
|
380
|
+
_name.current = name;
|
381
|
+
_fieldIds.current = fields;
|
382
|
+
control._names.array.add(name);
|
370
383
|
useSubscribe({
|
371
384
|
callback: ({ values, name: fieldArrayName }) => {
|
372
|
-
if (fieldArrayName ===
|
373
|
-
setFields(mapIds(get(values,
|
385
|
+
if (fieldArrayName === _name.current || !fieldArrayName) {
|
386
|
+
setFields(mapIds(get(values, _name.current), keyName));
|
374
387
|
}
|
375
388
|
},
|
376
389
|
subject: control._subjects.array,
|
390
|
+
skipEarlySubscription: true,
|
377
391
|
});
|
378
|
-
_fieldIds.current = fields;
|
379
|
-
control._names.array.add(name);
|
380
392
|
const updateValues = React.useCallback((updatedFieldArrayValuesWithKey) => {
|
381
|
-
const updatedFieldArrayValues =
|
393
|
+
const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
|
382
394
|
set(control._formValues, name, updatedFieldArrayValues);
|
383
395
|
setFields(updatedFieldArrayValuesWithKey);
|
384
396
|
return updatedFieldArrayValues;
|
385
397
|
}, [control, name, keyName]);
|
386
398
|
const append$1 = (value, options) => {
|
387
399
|
const appendValue = convertToArrayPayload(value);
|
388
|
-
const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control.
|
389
|
-
control._updateFieldArray(
|
400
|
+
const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(appendValue, keyName));
|
401
|
+
control._updateFieldArray(name, append, {
|
390
402
|
argA: fillEmptyArray(value),
|
391
403
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
392
404
|
control._names.focus = getFocusFieldName(name, updatedFieldArrayValuesWithKey.length - appendValue.length, options);
|
393
405
|
};
|
394
406
|
const prepend$1 = (value, options) => {
|
395
|
-
const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control.
|
396
|
-
control._updateFieldArray(
|
407
|
+
const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
|
408
|
+
control._updateFieldArray(name, prepend, {
|
397
409
|
argA: fillEmptyArray(value),
|
398
410
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
399
411
|
control._names.focus = getFocusFieldName(name, 0, options);
|
400
412
|
};
|
401
413
|
const remove = (index) => {
|
402
|
-
const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control.
|
403
|
-
control._updateFieldArray(
|
414
|
+
const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index);
|
415
|
+
control._updateFieldArray(name, removeArrayAt, {
|
404
416
|
argA: index,
|
405
417
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
406
418
|
};
|
407
419
|
const insert$1 = (index, value, options) => {
|
408
|
-
const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control.
|
409
|
-
control._updateFieldArray(
|
420
|
+
const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
|
421
|
+
control._updateFieldArray(name, insert, {
|
410
422
|
argA: index,
|
411
423
|
argB: fillEmptyArray(value),
|
412
424
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
413
425
|
control._names.focus = getFocusFieldName(name, index, options);
|
414
426
|
};
|
415
427
|
const swap = (indexA, indexB) => {
|
416
|
-
const updatedFieldArrayValuesWithKey = mapCurrentIds(control.
|
428
|
+
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
417
429
|
swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
|
418
|
-
control._updateFieldArray(
|
430
|
+
control._updateFieldArray(name, swapArrayAt, {
|
419
431
|
argA: indexA,
|
420
432
|
argB: indexB,
|
421
433
|
}, updateValues(updatedFieldArrayValuesWithKey), false);
|
422
434
|
};
|
423
435
|
const move = (from, to) => {
|
424
|
-
const updatedFieldArrayValuesWithKey = mapCurrentIds(control.
|
436
|
+
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
425
437
|
moveArrayAt(updatedFieldArrayValuesWithKey, from, to);
|
426
|
-
control._updateFieldArray(
|
438
|
+
control._updateFieldArray(name, moveArrayAt, {
|
427
439
|
argA: from,
|
428
440
|
argB: to,
|
429
441
|
}, updateValues(updatedFieldArrayValuesWithKey), false);
|
430
442
|
};
|
431
443
|
const update = (index, value) => {
|
432
|
-
const updatedFieldArrayValuesWithKey = mapCurrentIds(control.
|
444
|
+
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
433
445
|
const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
|
434
446
|
_fieldIds.current = mapIds(updatedFieldArrayValues, keyName);
|
435
|
-
control._updateFieldArray(
|
447
|
+
control._updateFieldArray(name, updateAt, {
|
436
448
|
argA: index,
|
437
449
|
argB: value,
|
438
450
|
}, updateValues(_fieldIds.current), true, false);
|
439
451
|
};
|
440
452
|
const replace = (value) => {
|
441
453
|
const updatedFieldArrayValuesWithKey = mapIds(convertToArrayPayload(value), keyName);
|
442
|
-
control._updateFieldArray(
|
454
|
+
control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
|
443
455
|
};
|
444
456
|
React.useEffect(() => {
|
445
457
|
control._stateFlags.action = false;
|
@@ -466,7 +478,7 @@ const useFieldArray = (props) => {
|
|
466
478
|
React.useEffect(() => {
|
467
479
|
!get(control._formValues, name) && set(control._formValues, name, []);
|
468
480
|
return () => {
|
469
|
-
if (control.
|
481
|
+
if (control._options.shouldUnregister || shouldUnregister) {
|
470
482
|
control.unregister(name);
|
471
483
|
}
|
472
484
|
};
|
@@ -484,6 +496,8 @@ const useFieldArray = (props) => {
|
|
484
496
|
};
|
485
497
|
};
|
486
498
|
|
499
|
+
var isFunction = (value) => typeof value === 'function';
|
500
|
+
|
487
501
|
function cloneObject(data) {
|
488
502
|
let copy;
|
489
503
|
const isArray = Array.isArray(data);
|
@@ -496,6 +510,10 @@ function cloneObject(data) {
|
|
496
510
|
else if (isArray || isObject(data)) {
|
497
511
|
copy = isArray ? [] : {};
|
498
512
|
for (const key in data) {
|
513
|
+
if (isFunction(data[key])) {
|
514
|
+
copy = data;
|
515
|
+
break;
|
516
|
+
}
|
499
517
|
copy[key] = cloneObject(data[key]);
|
500
518
|
}
|
501
519
|
}
|
@@ -508,12 +526,12 @@ function cloneObject(data) {
|
|
508
526
|
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
509
527
|
|
510
528
|
function deepEqual(object1, object2) {
|
511
|
-
if (isPrimitive(object1) ||
|
512
|
-
isPrimitive(object2) ||
|
513
|
-
isDateObject(object1) ||
|
514
|
-
isDateObject(object2)) {
|
529
|
+
if (isPrimitive(object1) || isPrimitive(object2)) {
|
515
530
|
return object1 === object2;
|
516
531
|
}
|
532
|
+
if (isDateObject(object1) && isDateObject(object2)) {
|
533
|
+
return object1.getTime() === object2.getTime();
|
534
|
+
}
|
517
535
|
const keys1 = Object.keys(object1);
|
518
536
|
const keys2 = Object.keys(object2);
|
519
537
|
if (keys1.length !== keys2.length) {
|
@@ -526,8 +544,9 @@ function deepEqual(object1, object2) {
|
|
526
544
|
}
|
527
545
|
if (key !== 'ref') {
|
528
546
|
const val2 = object2[key];
|
529
|
-
if ((
|
530
|
-
(isObject(
|
547
|
+
if ((isDateObject(val1) && isDateObject(val2)) ||
|
548
|
+
(isObject(val1) && isObject(val2)) ||
|
549
|
+
(Array.isArray(val1) && Array.isArray(val2))
|
531
550
|
? !deepEqual(val1, val2)
|
532
551
|
: val1 !== val2) {
|
533
552
|
return false;
|
@@ -547,10 +566,6 @@ var getValidationModes = (mode) => ({
|
|
547
566
|
|
548
567
|
var isBoolean = (value) => typeof value === 'boolean';
|
549
568
|
|
550
|
-
var isFileInput = (element) => element.type === 'file';
|
551
|
-
|
552
|
-
var isFunction = (value) => typeof value === 'function';
|
553
|
-
|
554
569
|
var isHTMLElement = (value) => value instanceof HTMLElement;
|
555
570
|
|
556
571
|
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
@@ -565,7 +580,7 @@ var isWeb = typeof window !== 'undefined' &&
|
|
565
580
|
typeof window.HTMLElement !== 'undefined' &&
|
566
581
|
typeof document !== 'undefined';
|
567
582
|
|
568
|
-
var live = (ref) =>
|
583
|
+
var live = (ref) => isHTMLElement(ref) && document.contains(ref);
|
569
584
|
|
570
585
|
class Subscription {
|
571
586
|
constructor() {
|
@@ -652,6 +667,8 @@ function unset(object, path) {
|
|
652
667
|
return object;
|
653
668
|
}
|
654
669
|
|
670
|
+
var isFileInput = (element) => element.type === 'file';
|
671
|
+
|
655
672
|
const defaultResult = {
|
656
673
|
value: false,
|
657
674
|
isValid: false,
|
@@ -973,8 +990,7 @@ const defaultOptions = {
|
|
973
990
|
};
|
974
991
|
const isWindowUndefined = typeof window === 'undefined';
|
975
992
|
function createFormControl(props = {}) {
|
976
|
-
let
|
977
|
-
let _delayCallback;
|
993
|
+
let _options = Object.assign(Object.assign({}, defaultOptions), props);
|
978
994
|
let _formState = {
|
979
995
|
isDirty: false,
|
980
996
|
isValidating: false,
|
@@ -988,8 +1004,8 @@ function createFormControl(props = {}) {
|
|
988
1004
|
errors: {},
|
989
1005
|
};
|
990
1006
|
let _fields = {};
|
991
|
-
let _defaultValues =
|
992
|
-
let _formValues =
|
1007
|
+
let _defaultValues = _options.defaultValues || {};
|
1008
|
+
let _formValues = _options.shouldUnregister
|
993
1009
|
? {}
|
994
1010
|
: cloneObject(_defaultValues);
|
995
1011
|
let _stateFlags = {
|
@@ -997,14 +1013,15 @@ function createFormControl(props = {}) {
|
|
997
1013
|
mount: false,
|
998
1014
|
watch: false,
|
999
1015
|
};
|
1000
|
-
let _timer = 0;
|
1001
1016
|
let _names = {
|
1002
1017
|
mount: new Set(),
|
1003
1018
|
unMount: new Set(),
|
1004
1019
|
array: new Set(),
|
1005
1020
|
watch: new Set(),
|
1006
1021
|
};
|
1007
|
-
let
|
1022
|
+
let delayErrorCallback;
|
1023
|
+
let timer = 0;
|
1024
|
+
let validateFields = {};
|
1008
1025
|
const _proxyFormState = {
|
1009
1026
|
isDirty: false,
|
1010
1027
|
dirtyFields: false,
|
@@ -1019,37 +1036,125 @@ function createFormControl(props = {}) {
|
|
1019
1036
|
array: new Subject(),
|
1020
1037
|
state: new Subject(),
|
1021
1038
|
};
|
1022
|
-
const
|
1023
|
-
const
|
1024
|
-
const
|
1039
|
+
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
1040
|
+
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
1041
|
+
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
1025
1042
|
const debounce = (callback, wait) => (...args) => {
|
1026
|
-
clearTimeout(
|
1027
|
-
|
1043
|
+
clearTimeout(timer);
|
1044
|
+
timer = window.setTimeout(() => callback(...args), wait);
|
1028
1045
|
};
|
1029
|
-
const isFieldWatched = (name) =>
|
1030
|
-
_names.
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1046
|
+
const isFieldWatched = (name, isBlurEvent) => !isBlurEvent &&
|
1047
|
+
(_names.watchAll ||
|
1048
|
+
_names.watch.has(name) ||
|
1049
|
+
_names.watch.has((name.match(/\w+/) || [])[0]));
|
1050
|
+
const _updateValid = async (shouldSkipRender) => {
|
1051
|
+
let isValid = false;
|
1052
|
+
if (_proxyFormState.isValid) {
|
1053
|
+
isValid = _options.resolver
|
1054
|
+
? isEmptyObject((await executeResolver()).errors)
|
1055
|
+
: await executeBuildInValidation(_fields, true);
|
1056
|
+
if (!shouldSkipRender && isValid !== _formState.isValid) {
|
1057
|
+
_formState.isValid = isValid;
|
1058
|
+
_subjects.state.next({
|
1059
|
+
isValid,
|
1060
|
+
});
|
1061
|
+
}
|
1062
|
+
}
|
1063
|
+
return isValid;
|
1064
|
+
};
|
1065
|
+
const _updateFieldArray = (name, method, args, values = [], shouldSetValues = true, shouldSetFields = true) => {
|
1066
|
+
_stateFlags.action = true;
|
1067
|
+
if (shouldSetFields && get(_fields, name)) {
|
1068
|
+
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
1069
|
+
shouldSetValues && set(_fields, name, fieldValues);
|
1070
|
+
}
|
1071
|
+
if (Array.isArray(get(_formState.errors, name))) {
|
1072
|
+
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
1073
|
+
shouldSetValues && set(_formState.errors, name, errors);
|
1074
|
+
unsetEmptyArray(_formState.errors, name);
|
1075
|
+
}
|
1076
|
+
if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
|
1077
|
+
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
1078
|
+
shouldSetValues &&
|
1079
|
+
set(_formState.touchedFields, name, touchedFields);
|
1080
|
+
unsetEmptyArray(_formState.touchedFields, name);
|
1081
|
+
}
|
1082
|
+
if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
|
1083
|
+
updateFieldArrayDirty(name, values);
|
1084
|
+
}
|
1034
1085
|
_subjects.state.next({
|
1086
|
+
isDirty: _getDirty(name, values),
|
1087
|
+
dirtyFields: _formState.dirtyFields,
|
1035
1088
|
errors: _formState.errors,
|
1089
|
+
isValid: _formState.isValid,
|
1036
1090
|
});
|
1037
1091
|
};
|
1038
|
-
const
|
1039
|
-
|
1092
|
+
const updateErrors = (name, error) => (set(_formState.errors, name, error),
|
1093
|
+
_subjects.state.next({
|
1094
|
+
errors: _formState.errors,
|
1095
|
+
}));
|
1096
|
+
const updateValidAndValue = (name, shouldSkipSetValueAs, ref) => {
|
1097
|
+
const field = get(_fields, name);
|
1098
|
+
if (field) {
|
1099
|
+
const defaultValue = get(_formValues, name, get(_defaultValues, name));
|
1100
|
+
isUndefined(defaultValue) ||
|
1101
|
+
(ref && ref.defaultChecked) ||
|
1102
|
+
shouldSkipSetValueAs
|
1103
|
+
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
1104
|
+
: setFieldValue(name, defaultValue);
|
1105
|
+
}
|
1106
|
+
_stateFlags.mount && _updateValid();
|
1107
|
+
};
|
1108
|
+
const updateTouchAndDirty = (name, fieldValue, isCurrentTouched, shouldRender = true) => {
|
1109
|
+
let isFieldDirty = false;
|
1110
|
+
const output = {
|
1111
|
+
name,
|
1112
|
+
};
|
1113
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1114
|
+
if (_proxyFormState.isDirty) {
|
1115
|
+
const isPreviousFormDirty = _formState.isDirty;
|
1116
|
+
_formState.isDirty = output.isDirty = _getDirty();
|
1117
|
+
isFieldDirty = isPreviousFormDirty !== output.isDirty;
|
1118
|
+
}
|
1119
|
+
if (_proxyFormState.dirtyFields && !isCurrentTouched) {
|
1120
|
+
const isPreviousFieldDirty = get(_formState.dirtyFields, name);
|
1121
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
1122
|
+
isCurrentFieldPristine
|
1123
|
+
? unset(_formState.dirtyFields, name)
|
1124
|
+
: set(_formState.dirtyFields, name, true);
|
1125
|
+
output.dirtyFields = _formState.dirtyFields;
|
1126
|
+
isFieldDirty =
|
1127
|
+
isFieldDirty ||
|
1128
|
+
isPreviousFieldDirty !== get(_formState.dirtyFields, name);
|
1129
|
+
}
|
1130
|
+
if (isCurrentTouched && !isPreviousFieldTouched) {
|
1131
|
+
set(_formState.touchedFields, name, isCurrentTouched);
|
1132
|
+
output.touchedFields = _formState.touchedFields;
|
1133
|
+
isFieldDirty =
|
1134
|
+
isFieldDirty ||
|
1135
|
+
(_proxyFormState.touchedFields &&
|
1136
|
+
isPreviousFieldTouched !== isCurrentTouched);
|
1137
|
+
}
|
1138
|
+
isFieldDirty && shouldRender && _subjects.state.next(output);
|
1139
|
+
return isFieldDirty ? output : {};
|
1140
|
+
};
|
1141
|
+
const updateFieldArrayDirty = (name, value) => (set(_formState.dirtyFields, name, setFieldArrayDirtyFields(value, get(_defaultValues, name, []), get(_formState.dirtyFields, name, []))),
|
1142
|
+
unsetEmptyArray(_formState.dirtyFields, name));
|
1143
|
+
const shouldRenderByError = async (shouldSkipRender, name, isValid, error, fieldState) => {
|
1144
|
+
const previousFieldError = get(_formState.errors, name);
|
1040
1145
|
const shouldUpdateValid = _proxyFormState.isValid && _formState.isValid !== isValid;
|
1041
1146
|
if (props.delayError && error) {
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1147
|
+
delayErrorCallback =
|
1148
|
+
delayErrorCallback || debounce(updateErrors, props.delayError);
|
1149
|
+
delayErrorCallback(name, error);
|
1045
1150
|
}
|
1046
1151
|
else {
|
1047
|
-
clearTimeout(
|
1152
|
+
clearTimeout(timer);
|
1048
1153
|
error
|
1049
1154
|
? set(_formState.errors, name, error)
|
1050
1155
|
: unset(_formState.errors, name);
|
1051
1156
|
}
|
1052
|
-
if (((error ? !deepEqual(
|
1157
|
+
if (((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
1053
1158
|
!isEmptyObject(fieldState) ||
|
1054
1159
|
shouldUpdateValid) &&
|
1055
1160
|
!shouldSkipRender) {
|
@@ -1057,138 +1162,171 @@ function createFormControl(props = {}) {
|
|
1057
1162
|
_formState = Object.assign(Object.assign({}, _formState), updatedFormState);
|
1058
1163
|
_subjects.state.next(updatedFormState);
|
1059
1164
|
}
|
1060
|
-
|
1061
|
-
if (_proxyFormState.isValidating && !
|
1165
|
+
validateFields[name]--;
|
1166
|
+
if (_proxyFormState.isValidating && !validateFields[name]) {
|
1062
1167
|
_subjects.state.next({
|
1063
1168
|
isValidating: false,
|
1064
1169
|
});
|
1065
|
-
|
1170
|
+
validateFields = {};
|
1066
1171
|
}
|
1067
1172
|
};
|
1173
|
+
const executeResolver = async (name) => _options.resolver
|
1174
|
+
? await _options.resolver(Object.assign({}, _formValues), _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation))
|
1175
|
+
: {};
|
1176
|
+
const executeResolverValidation = async (names) => {
|
1177
|
+
const { errors } = await executeResolver();
|
1178
|
+
if (names) {
|
1179
|
+
for (const name of names) {
|
1180
|
+
const error = get(errors, name);
|
1181
|
+
error
|
1182
|
+
? set(_formState.errors, name, error)
|
1183
|
+
: unset(_formState.errors, name);
|
1184
|
+
}
|
1185
|
+
}
|
1186
|
+
else {
|
1187
|
+
_formState.errors = errors;
|
1188
|
+
}
|
1189
|
+
return errors;
|
1190
|
+
};
|
1191
|
+
const executeBuildInValidation = async (fields, shouldOnlyCheckValid, context = {
|
1192
|
+
valid: true,
|
1193
|
+
}) => {
|
1194
|
+
for (const name in fields) {
|
1195
|
+
const field = fields[name];
|
1196
|
+
if (field) {
|
1197
|
+
const fieldReference = field._f;
|
1198
|
+
const fieldValue = omit(field, '_f');
|
1199
|
+
if (fieldReference) {
|
1200
|
+
const fieldError = await validateField(field, get(_formValues, fieldReference.name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation);
|
1201
|
+
if (fieldError[fieldReference.name]) {
|
1202
|
+
context.valid = false;
|
1203
|
+
if (shouldOnlyCheckValid) {
|
1204
|
+
break;
|
1205
|
+
}
|
1206
|
+
}
|
1207
|
+
if (!shouldOnlyCheckValid) {
|
1208
|
+
fieldError[fieldReference.name]
|
1209
|
+
? set(_formState.errors, fieldReference.name, fieldError[fieldReference.name])
|
1210
|
+
: unset(_formState.errors, fieldReference.name);
|
1211
|
+
}
|
1212
|
+
}
|
1213
|
+
fieldValue &&
|
1214
|
+
(await executeBuildInValidation(fieldValue, shouldOnlyCheckValid, context));
|
1215
|
+
}
|
1216
|
+
}
|
1217
|
+
return context.valid;
|
1218
|
+
};
|
1219
|
+
const _removeUnmounted = () => {
|
1220
|
+
for (const name of _names.unMount) {
|
1221
|
+
const field = get(_fields, name);
|
1222
|
+
field &&
|
1223
|
+
(field._f.refs
|
1224
|
+
? field._f.refs.every((ref) => !live(ref))
|
1225
|
+
: !live(field._f.ref)) &&
|
1226
|
+
unregister(name);
|
1227
|
+
}
|
1228
|
+
_names.unMount = new Set();
|
1229
|
+
};
|
1230
|
+
const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
|
1231
|
+
!deepEqual(getValues(), _defaultValues));
|
1232
|
+
const _getWatch = (names, defaultValue, isGlobal) => {
|
1233
|
+
const fieldValues = Object.assign({}, (_stateFlags.mount
|
1234
|
+
? _formValues
|
1235
|
+
: isUndefined(defaultValue)
|
1236
|
+
? _defaultValues
|
1237
|
+
: isString(names)
|
1238
|
+
? { [names]: defaultValue }
|
1239
|
+
: defaultValue));
|
1240
|
+
if (names) {
|
1241
|
+
const result = convertToArrayPayload(names).map((fieldName) => (isGlobal && _names.watch.add(fieldName),
|
1242
|
+
get(fieldValues, fieldName)));
|
1243
|
+
return Array.isArray(names) ? result : result[0];
|
1244
|
+
}
|
1245
|
+
isGlobal && (_names.watchAll = true);
|
1246
|
+
return fieldValues;
|
1247
|
+
};
|
1248
|
+
const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []);
|
1068
1249
|
const setFieldValue = (name, value, options = {}, shouldRender) => {
|
1069
1250
|
const field = get(_fields, name);
|
1070
1251
|
let fieldValue = value;
|
1071
1252
|
if (field) {
|
1072
|
-
const
|
1073
|
-
if (
|
1074
|
-
set(_formValues, name, getFieldValueAs(value,
|
1253
|
+
const fieldReference = field._f;
|
1254
|
+
if (fieldReference) {
|
1255
|
+
set(_formValues, name, getFieldValueAs(value, fieldReference));
|
1075
1256
|
fieldValue =
|
1076
|
-
isWeb && isHTMLElement(
|
1257
|
+
isWeb && isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
|
1077
1258
|
? ''
|
1078
1259
|
: value;
|
1079
|
-
if (
|
1080
|
-
|
1260
|
+
if (isMultipleSelect(fieldReference.ref)) {
|
1261
|
+
[...fieldReference.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
|
1081
1262
|
}
|
1082
|
-
else if (
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
if (isCheckBoxInput(_f.ref)) {
|
1087
|
-
_f.refs.length > 1
|
1088
|
-
? _f.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(fieldValue)
|
1263
|
+
else if (fieldReference.refs) {
|
1264
|
+
if (isCheckBoxInput(fieldReference.ref)) {
|
1265
|
+
fieldReference.refs.length > 1
|
1266
|
+
? fieldReference.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(fieldValue)
|
1089
1267
|
? !!fieldValue.find((data) => data === checkboxRef.value)
|
1090
1268
|
: fieldValue === checkboxRef.value))
|
1091
|
-
: (
|
1269
|
+
: (fieldReference.refs[0].checked = !!fieldValue);
|
1092
1270
|
}
|
1093
1271
|
else {
|
1094
|
-
|
1272
|
+
fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
|
1095
1273
|
}
|
1096
1274
|
}
|
1097
1275
|
else {
|
1098
|
-
|
1276
|
+
fieldReference.ref.value = fieldValue;
|
1099
1277
|
}
|
1100
|
-
|
1278
|
+
shouldRender &&
|
1101
1279
|
_subjects.control.next({
|
1102
1280
|
values: _formValues,
|
1103
1281
|
name,
|
1104
1282
|
});
|
1105
|
-
}
|
1106
1283
|
}
|
1107
1284
|
}
|
1108
1285
|
(options.shouldDirty || options.shouldTouch) &&
|
1109
|
-
|
1286
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch);
|
1110
1287
|
options.shouldValidate && trigger(name);
|
1111
1288
|
};
|
1112
|
-
const
|
1113
|
-
const
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
if (_proxyFormState.dirtyFields && !isCurrentTouched) {
|
1124
|
-
const isPreviousFieldDirty = get(_formState.dirtyFields, name);
|
1125
|
-
const isCurrentFieldDirty = !deepEqual(get(_defaultValues, name), inputValue);
|
1126
|
-
isCurrentFieldDirty
|
1127
|
-
? set(_formState.dirtyFields, name, true)
|
1128
|
-
: unset(_formState.dirtyFields, name);
|
1129
|
-
state.dirtyFields = _formState.dirtyFields;
|
1130
|
-
isChanged =
|
1131
|
-
isChanged || isPreviousFieldDirty !== get(_formState.dirtyFields, name);
|
1289
|
+
const setValues = (name, value, options) => {
|
1290
|
+
for (const fieldKey in value) {
|
1291
|
+
const fieldValue = value[fieldKey];
|
1292
|
+
const fieldName = `${name}.${fieldKey}`;
|
1293
|
+
const field = get(_fields, fieldName);
|
1294
|
+
(_names.array.has(name) ||
|
1295
|
+
!isPrimitive(fieldValue) ||
|
1296
|
+
(field && !field._f)) &&
|
1297
|
+
!isDateObject(fieldValue)
|
1298
|
+
? setValues(fieldName, fieldValue, options)
|
1299
|
+
: setFieldValue(fieldName, fieldValue, options, true);
|
1132
1300
|
}
|
1133
|
-
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1134
|
-
if (isCurrentTouched && !isPreviousFieldTouched) {
|
1135
|
-
set(_formState.touchedFields, name, isCurrentTouched);
|
1136
|
-
state.touchedFields = _formState.touchedFields;
|
1137
|
-
isChanged =
|
1138
|
-
isChanged ||
|
1139
|
-
(_proxyFormState.touchedFields &&
|
1140
|
-
isPreviousFieldTouched !== isCurrentTouched);
|
1141
|
-
}
|
1142
|
-
isChanged && shouldRender && _subjects.state.next(state);
|
1143
|
-
return isChanged ? state : {};
|
1144
|
-
};
|
1145
|
-
const executeResolver = async (name) => {
|
1146
|
-
return formOptions.resolver
|
1147
|
-
? await formOptions.resolver(Object.assign({}, _formValues), formOptions.context, getResolverOptions(name || _names.mount, _fields, formOptions.criteriaMode, formOptions.shouldUseNativeValidation))
|
1148
|
-
: {};
|
1149
1301
|
};
|
1150
|
-
const
|
1151
|
-
const
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1302
|
+
const setValue = (name, value, options = {}) => {
|
1303
|
+
const field = get(_fields, name);
|
1304
|
+
const isFieldArray = _names.array.has(name);
|
1305
|
+
set(_formValues, name, value);
|
1306
|
+
if (isFieldArray) {
|
1307
|
+
_subjects.array.next({
|
1308
|
+
name,
|
1309
|
+
values: _formValues,
|
1310
|
+
});
|
1311
|
+
if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) &&
|
1312
|
+
options.shouldDirty) {
|
1313
|
+
updateFieldArrayDirty(name, value);
|
1314
|
+
_subjects.state.next({
|
1315
|
+
name,
|
1316
|
+
dirtyFields: _formState.dirtyFields,
|
1317
|
+
isDirty: _getDirty(name, value),
|
1318
|
+
});
|
1158
1319
|
}
|
1159
1320
|
}
|
1160
1321
|
else {
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
};
|
1165
|
-
const validateForm = async (_fields, shouldCheckValid, context = {
|
1166
|
-
valid: true,
|
1167
|
-
}) => {
|
1168
|
-
for (const name in _fields) {
|
1169
|
-
const field = _fields[name];
|
1170
|
-
if (field) {
|
1171
|
-
const _f = field._f;
|
1172
|
-
const fieldValue = omit(field, '_f');
|
1173
|
-
if (_f) {
|
1174
|
-
const fieldError = await validateField(field, get(_formValues, _f.name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation);
|
1175
|
-
if (fieldError[_f.name]) {
|
1176
|
-
context.valid = false;
|
1177
|
-
if (shouldCheckValid) {
|
1178
|
-
break;
|
1179
|
-
}
|
1180
|
-
}
|
1181
|
-
if (!shouldCheckValid) {
|
1182
|
-
fieldError[_f.name]
|
1183
|
-
? set(_formState.errors, _f.name, fieldError[_f.name])
|
1184
|
-
: unset(_formState.errors, _f.name);
|
1185
|
-
}
|
1186
|
-
}
|
1187
|
-
fieldValue &&
|
1188
|
-
(await validateForm(fieldValue, shouldCheckValid, context));
|
1189
|
-
}
|
1322
|
+
field && !field._f && !isNullOrUndefined(value)
|
1323
|
+
? setValues(name, value, options)
|
1324
|
+
: setFieldValue(name, value, options, true);
|
1190
1325
|
}
|
1191
|
-
|
1326
|
+
isFieldWatched(name) && _subjects.state.next({});
|
1327
|
+
_subjects.watch.next({
|
1328
|
+
name,
|
1329
|
+
});
|
1192
1330
|
};
|
1193
1331
|
const handleChange = async (event) => {
|
1194
1332
|
const target = event.target;
|
@@ -1197,22 +1335,22 @@ function createFormControl(props = {}) {
|
|
1197
1335
|
if (field) {
|
1198
1336
|
let error;
|
1199
1337
|
let isValid;
|
1200
|
-
const
|
1338
|
+
const fieldValue = target.type ? getFieldValue(field._f) : target.value;
|
1201
1339
|
const isBlurEvent = event.type === EVENTS.BLUR;
|
1202
|
-
|
1203
|
-
|
1340
|
+
const shouldSkipValidation = (!hasValidation(field._f) &&
|
1341
|
+
!_options.resolver &&
|
1342
|
+
!get(_formState.errors, name) &&
|
1343
|
+
!field._f.deps) ||
|
1344
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
|
1345
|
+
const isWatched = isFieldWatched(name, isBlurEvent);
|
1346
|
+
if (isBlurEvent) {
|
1347
|
+
field._f.onBlur && field._f.onBlur(event);
|
1204
1348
|
}
|
1205
1349
|
else if (field._f.onChange) {
|
1206
1350
|
field._f.onChange(event);
|
1207
1351
|
}
|
1208
|
-
|
1209
|
-
|
1210
|
-
!get(_formState.errors, name) &&
|
1211
|
-
!field._f.deps) ||
|
1212
|
-
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, reValidateMode, validationMode);
|
1213
|
-
const isWatched = !isBlurEvent && isFieldWatched(name);
|
1214
|
-
set(_formValues, name, inputValue);
|
1215
|
-
const fieldState = updateTouchAndDirtyState(name, inputValue, isBlurEvent, false);
|
1352
|
+
set(_formValues, name, fieldValue);
|
1353
|
+
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
|
1216
1354
|
const shouldRender = !isEmptyObject(fieldState) || isWatched;
|
1217
1355
|
!isBlurEvent &&
|
1218
1356
|
_subjects.watch.next({
|
@@ -1224,12 +1362,12 @@ function createFormControl(props = {}) {
|
|
1224
1362
|
_subjects.state.next(Object.assign({ name }, (isWatched ? {} : fieldState))));
|
1225
1363
|
}
|
1226
1364
|
!isBlurEvent && isWatched && _subjects.state.next({});
|
1227
|
-
|
1365
|
+
validateFields[name] = validateFields[name] ? +1 : 1;
|
1228
1366
|
_proxyFormState.isValidating &&
|
1229
1367
|
_subjects.state.next({
|
1230
1368
|
isValidating: true,
|
1231
1369
|
});
|
1232
|
-
if (
|
1370
|
+
if (_options.resolver) {
|
1233
1371
|
const { errors } = await executeResolver([name]);
|
1234
1372
|
error = get(errors, name);
|
1235
1373
|
if (isCheckBoxInput(target) && !error) {
|
@@ -1245,169 +1383,41 @@ function createFormControl(props = {}) {
|
|
1245
1383
|
isValid = isEmptyObject(errors);
|
1246
1384
|
}
|
1247
1385
|
else {
|
1248
|
-
error = (await validateField(field, get(_formValues, name),
|
1386
|
+
error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
|
1249
1387
|
isValid = await _updateValid(true);
|
1250
1388
|
}
|
1251
|
-
|
1252
|
-
|
1253
|
-
}
|
1254
|
-
shouldRenderBaseOnError(false, name, isValid, error, fieldState);
|
1255
|
-
}
|
1256
|
-
};
|
1257
|
-
const _updateValidAndInputValue = (name, shouldSkipValueAs, ref) => {
|
1258
|
-
const field = get(_fields, name);
|
1259
|
-
if (field) {
|
1260
|
-
const fieldValue = get(_formValues, name);
|
1261
|
-
const defaultValue = isUndefined(fieldValue)
|
1262
|
-
? get(_defaultValues, name)
|
1263
|
-
: fieldValue;
|
1264
|
-
if (isUndefined(defaultValue) ||
|
1265
|
-
(ref && ref.defaultChecked) ||
|
1266
|
-
shouldSkipValueAs) {
|
1267
|
-
set(_formValues, name, shouldSkipValueAs ? defaultValue : getFieldValue(field._f));
|
1268
|
-
}
|
1269
|
-
else {
|
1270
|
-
setFieldValue(name, defaultValue);
|
1271
|
-
}
|
1272
|
-
}
|
1273
|
-
_stateFlags.mount && _updateValid();
|
1274
|
-
};
|
1275
|
-
const _getIsDirty = (name, data) => {
|
1276
|
-
name && data && set(_formValues, name, data);
|
1277
|
-
return !deepEqual(Object.assign({}, getValues()), _defaultValues);
|
1278
|
-
};
|
1279
|
-
const _updateValid = async (skipRender) => {
|
1280
|
-
let isValid = false;
|
1281
|
-
if (_proxyFormState.isValid) {
|
1282
|
-
isValid = formOptions.resolver
|
1283
|
-
? isEmptyObject((await executeResolver()).errors)
|
1284
|
-
: await validateForm(_fields, true);
|
1285
|
-
if (!skipRender && isValid !== _formState.isValid) {
|
1286
|
-
_formState.isValid = isValid;
|
1287
|
-
_subjects.state.next({
|
1288
|
-
isValid,
|
1289
|
-
});
|
1290
|
-
}
|
1291
|
-
}
|
1292
|
-
return isValid;
|
1293
|
-
};
|
1294
|
-
const setValues = (name, value, options) => Object.entries(value).forEach(([fieldKey, fieldValue]) => {
|
1295
|
-
const fieldName = `${name}.${fieldKey}`;
|
1296
|
-
const field = get(_fields, fieldName);
|
1297
|
-
(_names.array.has(name) ||
|
1298
|
-
!isPrimitive(fieldValue) ||
|
1299
|
-
(field && !field._f)) &&
|
1300
|
-
!isDateObject(fieldValue)
|
1301
|
-
? setValues(fieldName, fieldValue, options)
|
1302
|
-
: setFieldValue(fieldName, fieldValue, options, true);
|
1303
|
-
});
|
1304
|
-
const _getWatch = (fieldNames, defaultValue, isMounted, isGlobal) => {
|
1305
|
-
const fieldValues = Object.assign({}, (isMounted || _stateFlags.mount
|
1306
|
-
? _formValues
|
1307
|
-
: isUndefined(defaultValue)
|
1308
|
-
? _defaultValues
|
1309
|
-
: isString(fieldNames)
|
1310
|
-
? { [fieldNames]: defaultValue }
|
1311
|
-
: defaultValue));
|
1312
|
-
if (!fieldNames) {
|
1313
|
-
isGlobal && (_names.watchAll = true);
|
1314
|
-
return fieldValues;
|
1389
|
+
field._f.deps && trigger(field._f.deps);
|
1390
|
+
shouldRenderByError(false, name, isValid, error, fieldState);
|
1315
1391
|
}
|
1316
|
-
const result = [];
|
1317
|
-
for (const fieldName of convertToArrayPayload(fieldNames)) {
|
1318
|
-
isGlobal && _names.watch.add(fieldName);
|
1319
|
-
result.push(get(fieldValues, fieldName));
|
1320
|
-
}
|
1321
|
-
return Array.isArray(fieldNames) ? result : result[0];
|
1322
|
-
};
|
1323
|
-
const _updateFieldArray = (keyName, name, method, args, values = [], shouldSet = true, shouldSetFields = true) => {
|
1324
|
-
let output;
|
1325
|
-
_stateFlags.action = true;
|
1326
|
-
if (shouldSetFields && get(_fields, name)) {
|
1327
|
-
output = method(get(_fields, name), args.argA, args.argB);
|
1328
|
-
shouldSet && set(_fields, name, output);
|
1329
|
-
}
|
1330
|
-
if (Array.isArray(get(_formState.errors, name))) {
|
1331
|
-
const output = method(get(_formState.errors, name), args.argA, args.argB);
|
1332
|
-
shouldSet && set(_formState.errors, name, output);
|
1333
|
-
unsetEmptyArray(_formState.errors, name);
|
1334
|
-
}
|
1335
|
-
if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
|
1336
|
-
const output = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
1337
|
-
shouldSet && set(_formState.touchedFields, name, output);
|
1338
|
-
unsetEmptyArray(_formState.touchedFields, name);
|
1339
|
-
}
|
1340
|
-
if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
|
1341
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(values, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1342
|
-
values &&
|
1343
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(values, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1344
|
-
unsetEmptyArray(_formState.dirtyFields, name);
|
1345
|
-
}
|
1346
|
-
_subjects.state.next({
|
1347
|
-
isDirty: _getIsDirty(name, omitKey(values, keyName)),
|
1348
|
-
dirtyFields: _formState.dirtyFields,
|
1349
|
-
errors: _formState.errors,
|
1350
|
-
isValid: _formState.isValid,
|
1351
|
-
});
|
1352
|
-
};
|
1353
|
-
const _getFieldArrayValue = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, []);
|
1354
|
-
const setValue = (name, value, options = {}) => {
|
1355
|
-
const field = get(_fields, name);
|
1356
|
-
const isFieldArray = _names.array.has(name);
|
1357
|
-
set(_formValues, name, value);
|
1358
|
-
if (isFieldArray) {
|
1359
|
-
_subjects.array.next({
|
1360
|
-
name,
|
1361
|
-
values: _formValues,
|
1362
|
-
});
|
1363
|
-
if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) &&
|
1364
|
-
options.shouldDirty) {
|
1365
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(value, get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1366
|
-
_subjects.state.next({
|
1367
|
-
name,
|
1368
|
-
dirtyFields: _formState.dirtyFields,
|
1369
|
-
isDirty: _getIsDirty(name, value),
|
1370
|
-
});
|
1371
|
-
}
|
1372
|
-
}
|
1373
|
-
else {
|
1374
|
-
field && !field._f && !isNullOrUndefined(value)
|
1375
|
-
? setValues(name, value, options)
|
1376
|
-
: setFieldValue(name, value, options, true);
|
1377
|
-
}
|
1378
|
-
isFieldWatched(name) && _subjects.state.next({});
|
1379
|
-
_subjects.watch.next({
|
1380
|
-
name,
|
1381
|
-
});
|
1382
1392
|
};
|
1383
1393
|
const trigger = async (name, options = {}) => {
|
1384
|
-
const fieldNames = convertToArrayPayload(name);
|
1385
1394
|
let isValid;
|
1386
1395
|
let validationResult;
|
1396
|
+
const fieldNames = convertToArrayPayload(name);
|
1387
1397
|
_subjects.state.next({
|
1388
1398
|
isValidating: true,
|
1389
1399
|
});
|
1390
|
-
if (
|
1391
|
-
const
|
1392
|
-
isValid = isEmptyObject(
|
1400
|
+
if (_options.resolver) {
|
1401
|
+
const errors = await executeResolverValidation(isUndefined(name) ? name : fieldNames);
|
1402
|
+
isValid = isEmptyObject(errors);
|
1393
1403
|
validationResult = name
|
1394
|
-
? !fieldNames.some((name) => get(
|
1404
|
+
? !fieldNames.some((name) => get(errors, name))
|
1395
1405
|
: isValid;
|
1396
1406
|
}
|
1397
1407
|
else if (name) {
|
1398
1408
|
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
|
1399
1409
|
const field = get(_fields, fieldName);
|
1400
|
-
return await
|
1410
|
+
return await executeBuildInValidation(field && field._f ? { [fieldName]: field } : field);
|
1401
1411
|
}))).every(Boolean);
|
1402
1412
|
_updateValid();
|
1403
1413
|
}
|
1404
1414
|
else {
|
1405
|
-
validationResult = isValid = await
|
1415
|
+
validationResult = isValid = await executeBuildInValidation(_fields);
|
1406
1416
|
}
|
1407
1417
|
_subjects.state.next(Object.assign(Object.assign({}, (!isString(name) || isValid !== _formState.isValid ? {} : { name })), { errors: _formState.errors, isValid, isValidating: false }));
|
1408
|
-
|
1418
|
+
options.shouldFocus &&
|
1419
|
+
!validationResult &&
|
1409
1420
|
focusFieldBy(_fields, (key) => get(_formState.errors, key), name ? fieldNames : _names.mount);
|
1410
|
-
}
|
1411
1421
|
return validationResult;
|
1412
1422
|
};
|
1413
1423
|
const getValues = (fieldNames) => {
|
@@ -1436,88 +1446,83 @@ function createFormControl(props = {}) {
|
|
1436
1446
|
});
|
1437
1447
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
1438
1448
|
};
|
1439
|
-
const watch = (
|
1449
|
+
const watch = (name, defaultValue) => isFunction(name)
|
1440
1450
|
? _subjects.watch.subscribe({
|
1441
|
-
next: (info) =>
|
1451
|
+
next: (info) => name(_getWatch(undefined, defaultValue), info),
|
1442
1452
|
})
|
1443
|
-
: _getWatch(
|
1453
|
+
: _getWatch(name, defaultValue, true);
|
1444
1454
|
const unregister = (name, options = {}) => {
|
1445
|
-
for (const
|
1446
|
-
_names.mount.delete(
|
1447
|
-
_names.array.delete(
|
1448
|
-
if (get(_fields,
|
1455
|
+
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
1456
|
+
_names.mount.delete(fieldName);
|
1457
|
+
_names.array.delete(fieldName);
|
1458
|
+
if (get(_fields, fieldName)) {
|
1449
1459
|
if (!options.keepValue) {
|
1450
|
-
unset(_fields,
|
1451
|
-
unset(_formValues,
|
1460
|
+
unset(_fields, fieldName);
|
1461
|
+
unset(_formValues, fieldName);
|
1452
1462
|
}
|
1453
|
-
!options.keepError && unset(_formState.errors,
|
1454
|
-
!options.keepDirty && unset(_formState.dirtyFields,
|
1455
|
-
!options.keepTouched && unset(_formState.touchedFields,
|
1456
|
-
!
|
1463
|
+
!options.keepError && unset(_formState.errors, fieldName);
|
1464
|
+
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
1465
|
+
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
1466
|
+
!_options.shouldUnregister &&
|
1457
1467
|
!options.keepDefaultValue &&
|
1458
|
-
unset(_defaultValues,
|
1468
|
+
unset(_defaultValues, fieldName);
|
1459
1469
|
}
|
1460
1470
|
}
|
1461
1471
|
_subjects.watch.next({});
|
1462
|
-
_subjects.state.next(Object.assign(Object.assign({}, _formState), (!options.keepDirty ? {} : { isDirty:
|
1472
|
+
_subjects.state.next(Object.assign(Object.assign({}, _formState), (!options.keepDirty ? {} : { isDirty: _getDirty() })));
|
1463
1473
|
!options.keepIsValid && _updateValid();
|
1464
1474
|
};
|
1465
|
-
const registerFieldRef = (name, fieldRef, options) => {
|
1466
|
-
register(name, options);
|
1467
|
-
let field = get(_fields, name);
|
1468
|
-
const ref = isUndefined(fieldRef.value)
|
1469
|
-
? fieldRef.querySelectorAll
|
1470
|
-
? fieldRef.querySelectorAll('input,select,textarea')[0] ||
|
1471
|
-
fieldRef
|
1472
|
-
: fieldRef
|
1473
|
-
: fieldRef;
|
1474
|
-
const isRadioOrCheckbox = isRadioOrCheckboxFunction(ref);
|
1475
|
-
if (ref === field._f.ref ||
|
1476
|
-
(isRadioOrCheckbox &&
|
1477
|
-
compact(field._f.refs || []).find((option) => option === ref))) {
|
1478
|
-
return;
|
1479
|
-
}
|
1480
|
-
field = {
|
1481
|
-
_f: isRadioOrCheckbox
|
1482
|
-
? Object.assign(Object.assign({}, field._f), { refs: [
|
1483
|
-
...compact(field._f.refs || []).filter((ref) => isHTMLElement(ref) && document.contains(ref)),
|
1484
|
-
ref,
|
1485
|
-
], ref: { type: ref.type, name } }) : Object.assign(Object.assign({}, field._f), { ref }),
|
1486
|
-
};
|
1487
|
-
set(_fields, name, field);
|
1488
|
-
(!options || !options.disabled) &&
|
1489
|
-
_updateValidAndInputValue(name, false, ref);
|
1490
|
-
};
|
1491
1475
|
const register = (name, options = {}) => {
|
1492
1476
|
const field = get(_fields, name);
|
1493
1477
|
set(_fields, name, {
|
1494
1478
|
_f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
|
1495
1479
|
});
|
1496
1480
|
_names.mount.add(name);
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
}
|
1505
|
-
!field && _updateValidAndInputValue(name, true);
|
1481
|
+
!isUndefined(options.value) && set(_formValues, name, options.value);
|
1482
|
+
field
|
1483
|
+
? isBoolean(options.disabled) &&
|
1484
|
+
set(_formValues, name, options.disabled
|
1485
|
+
? undefined
|
1486
|
+
: get(_formValues, name, getFieldValue(field._f)))
|
1487
|
+
: updateValidAndValue(name, true);
|
1506
1488
|
return isWindowUndefined
|
1507
1489
|
? { name: name }
|
1508
1490
|
: Object.assign(Object.assign({ name }, (isBoolean(options.disabled)
|
1509
1491
|
? { disabled: options.disabled }
|
1510
1492
|
: {})), { onChange: handleChange, onBlur: handleChange, ref: (ref) => {
|
1511
1493
|
if (ref) {
|
1512
|
-
|
1494
|
+
register(name, options);
|
1495
|
+
let field = get(_fields, name);
|
1496
|
+
const fieldRef = isUndefined(ref.value)
|
1497
|
+
? ref.querySelectorAll
|
1498
|
+
? ref.querySelectorAll('input,select,textarea')[0] ||
|
1499
|
+
ref
|
1500
|
+
: ref
|
1501
|
+
: ref;
|
1502
|
+
const isRadioOrCheckbox = isRadioOrCheckboxFunction(fieldRef);
|
1503
|
+
if (fieldRef === field._f.ref ||
|
1504
|
+
(isRadioOrCheckbox &&
|
1505
|
+
compact(field._f.refs || []).find((option) => option === fieldRef))) {
|
1506
|
+
return;
|
1507
|
+
}
|
1508
|
+
field = {
|
1509
|
+
_f: isRadioOrCheckbox
|
1510
|
+
? Object.assign(Object.assign({}, field._f), { refs: [
|
1511
|
+
...compact(field._f.refs || []).filter(live),
|
1512
|
+
fieldRef,
|
1513
|
+
], ref: { type: fieldRef.type, name } }) : Object.assign(Object.assign({}, field._f), { ref: fieldRef }),
|
1514
|
+
};
|
1515
|
+
set(_fields, name, field);
|
1516
|
+
(!options || !options.disabled) &&
|
1517
|
+
updateValidAndValue(name, false, fieldRef);
|
1513
1518
|
}
|
1514
1519
|
else {
|
1515
1520
|
const field = get(_fields, name, {});
|
1516
|
-
const
|
1521
|
+
const shouldUnregister = _options.shouldUnregister || options.shouldUnregister;
|
1517
1522
|
if (field._f) {
|
1518
1523
|
field._f.mount = false;
|
1519
1524
|
}
|
1520
|
-
|
1525
|
+
shouldUnregister &&
|
1521
1526
|
!(isNameInFieldArray(_names.array, name) && _stateFlags.action) &&
|
1522
1527
|
_names.unMount.add(name);
|
1523
1528
|
}
|
@@ -1534,13 +1539,13 @@ function createFormControl(props = {}) {
|
|
1534
1539
|
isSubmitting: true,
|
1535
1540
|
});
|
1536
1541
|
try {
|
1537
|
-
if (
|
1542
|
+
if (_options.resolver) {
|
1538
1543
|
const { errors, values } = await executeResolver();
|
1539
1544
|
_formState.errors = errors;
|
1540
1545
|
fieldValues = values;
|
1541
1546
|
}
|
1542
1547
|
else {
|
1543
|
-
await
|
1548
|
+
await executeBuildInValidation(_fields);
|
1544
1549
|
}
|
1545
1550
|
if (isEmptyObject(_formState.errors) &&
|
1546
1551
|
Object.keys(_formState.errors).every((name) => get(fieldValues, name))) {
|
@@ -1552,7 +1557,7 @@ function createFormControl(props = {}) {
|
|
1552
1557
|
}
|
1553
1558
|
else {
|
1554
1559
|
onInvalid && (await onInvalid(_formState.errors, e));
|
1555
|
-
|
1560
|
+
_options.shouldFocusError &&
|
1556
1561
|
focusFieldBy(_fields, (key) => get(_formState.errors, key), _names.mount);
|
1557
1562
|
}
|
1558
1563
|
}
|
@@ -1572,39 +1577,41 @@ function createFormControl(props = {}) {
|
|
1572
1577
|
}
|
1573
1578
|
};
|
1574
1579
|
const reset = (formValues, keepStateOptions = {}) => {
|
1580
|
+
const hasUpdatedFormValues = !isEmptyObject(formValues);
|
1575
1581
|
const updatedValues = formValues || _defaultValues;
|
1576
|
-
const
|
1577
|
-
if (!keepStateOptions.
|
1578
|
-
|
1582
|
+
const cloneUpdatedValues = cloneObject(updatedValues);
|
1583
|
+
if (!keepStateOptions.keepDefaultValues) {
|
1584
|
+
_defaultValues = updatedValues;
|
1579
1585
|
}
|
1580
|
-
if (
|
1581
|
-
|
1582
|
-
const
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1586
|
+
if (!keepStateOptions.keepValues) {
|
1587
|
+
if (isWeb) {
|
1588
|
+
for (const name of _names.mount) {
|
1589
|
+
const field = get(_fields, name);
|
1590
|
+
if (field && field._f) {
|
1591
|
+
const fieldReference = Array.isArray(field._f.refs)
|
1592
|
+
? field._f.refs[0]
|
1593
|
+
: field._f.ref;
|
1594
|
+
try {
|
1595
|
+
isHTMLElement(fieldReference) &&
|
1596
|
+
fieldReference.closest('form').reset();
|
1597
|
+
break;
|
1598
|
+
}
|
1599
|
+
catch (_a) { }
|
1590
1600
|
}
|
1591
|
-
catch (_a) { }
|
1592
1601
|
}
|
1593
1602
|
}
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1603
|
+
_formValues = props.shouldUnregister
|
1604
|
+
? keepStateOptions.keepDefaultValues
|
1605
|
+
? _defaultValues
|
1606
|
+
: {}
|
1607
|
+
: cloneUpdatedValues;
|
1599
1608
|
_fields = {};
|
1600
1609
|
_subjects.control.next({
|
1601
|
-
values:
|
1602
|
-
? _defaultValues
|
1603
|
-
: Object.assign({}, updatedValues),
|
1610
|
+
values: hasUpdatedFormValues ? cloneUpdatedValues : _defaultValues,
|
1604
1611
|
});
|
1605
1612
|
_subjects.watch.next({});
|
1606
1613
|
_subjects.array.next({
|
1607
|
-
values,
|
1614
|
+
values: cloneUpdatedValues,
|
1608
1615
|
});
|
1609
1616
|
}
|
1610
1617
|
_names = {
|
@@ -1622,14 +1629,16 @@ function createFormControl(props = {}) {
|
|
1622
1629
|
isDirty: keepStateOptions.keepDirty
|
1623
1630
|
? _formState.isDirty
|
1624
1631
|
: keepStateOptions.keepDefaultValues
|
1625
|
-
? deepEqual(formValues, _defaultValues)
|
1632
|
+
? !deepEqual(formValues, _defaultValues)
|
1626
1633
|
: false,
|
1627
1634
|
isSubmitted: keepStateOptions.keepIsSubmitted
|
1628
1635
|
? _formState.isSubmitted
|
1629
1636
|
: false,
|
1630
1637
|
dirtyFields: keepStateOptions.keepDirty
|
1631
1638
|
? _formState.dirtyFields
|
1632
|
-
:
|
1639
|
+
: (keepStateOptions.keepDefaultValues && formValues
|
1640
|
+
? Object.entries(formValues).reduce((previous, [key, value]) => (Object.assign(Object.assign({}, previous), { [key]: value !== get(_defaultValues, key) })), {})
|
1641
|
+
: {}),
|
1633
1642
|
touchedFields: keepStateOptions.keepTouched
|
1634
1643
|
? _formState.touchedFields
|
1635
1644
|
: {},
|
@@ -1643,28 +1652,21 @@ function createFormControl(props = {}) {
|
|
1643
1652
|
!_proxyFormState.isValid || !!keepStateOptions.keepIsValid;
|
1644
1653
|
_stateFlags.watch = !!props.shouldUnregister;
|
1645
1654
|
};
|
1646
|
-
const setFocus = (name) =>
|
1647
|
-
|
1648
|
-
|
1649
|
-
const field = get(_fields, name);
|
1650
|
-
field &&
|
1651
|
-
(field._f.refs ? field._f.refs.every(live) : live(field._f.ref)) &&
|
1652
|
-
unregister(name);
|
1653
|
-
}
|
1654
|
-
_names.unMount = new Set();
|
1655
|
+
const setFocus = (name) => {
|
1656
|
+
const field = get(_fields, name)._f;
|
1657
|
+
(field.ref.focus ? field.ref : field.refs[0]).focus();
|
1655
1658
|
};
|
1656
1659
|
return {
|
1657
1660
|
control: {
|
1658
1661
|
register,
|
1659
1662
|
unregister,
|
1660
1663
|
_getWatch,
|
1661
|
-
|
1664
|
+
_getDirty,
|
1662
1665
|
_updateValid,
|
1663
|
-
|
1666
|
+
_removeUnmounted,
|
1664
1667
|
_updateFieldArray,
|
1665
|
-
|
1668
|
+
_getFieldArray,
|
1666
1669
|
_subjects,
|
1667
|
-
_shouldUnregister: formOptions.shouldUnregister,
|
1668
1670
|
_proxyFormState,
|
1669
1671
|
get _fields() {
|
1670
1672
|
return _fields;
|
@@ -1702,8 +1704,11 @@ function createFormControl(props = {}) {
|
|
1702
1704
|
set _formState(value) {
|
1703
1705
|
_formState = value;
|
1704
1706
|
},
|
1705
|
-
|
1706
|
-
|
1707
|
+
get _options() {
|
1708
|
+
return _options;
|
1709
|
+
},
|
1710
|
+
set _options(value) {
|
1711
|
+
_options = Object.assign(Object.assign({}, _options), value);
|
1707
1712
|
},
|
1708
1713
|
},
|
1709
1714
|
trigger,
|
@@ -1735,7 +1740,7 @@ function useForm(props = {}) {
|
|
1735
1740
|
errors: {},
|
1736
1741
|
});
|
1737
1742
|
if (_formControl.current) {
|
1738
|
-
_formControl.current.control.
|
1743
|
+
_formControl.current.control._options = props;
|
1739
1744
|
}
|
1740
1745
|
else {
|
1741
1746
|
_formControl.current = Object.assign(Object.assign({}, createFormControl(props)), { formState });
|
@@ -1759,7 +1764,7 @@ function useForm(props = {}) {
|
|
1759
1764
|
control._stateFlags.watch = false;
|
1760
1765
|
control._subjects.state.next({});
|
1761
1766
|
}
|
1762
|
-
control.
|
1767
|
+
control._removeUnmounted();
|
1763
1768
|
});
|
1764
1769
|
_formControl.current.formState = getProxyFormState(formState, control._proxyFormState);
|
1765
1770
|
return _formControl.current;
|
@@ -1773,18 +1778,14 @@ function useWatch(props) {
|
|
1773
1778
|
useSubscribe({
|
1774
1779
|
disabled,
|
1775
1780
|
subject: control._subjects.watch,
|
1776
|
-
callback: (
|
1777
|
-
if (
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
(
|
1782
|
-
|
1783
|
-
|
1784
|
-
updateValue(isObject(result)
|
1785
|
-
? Object.assign({}, result) : Array.isArray(result)
|
1786
|
-
? [...result]
|
1787
|
-
: result);
|
1781
|
+
callback: (formState) => {
|
1782
|
+
if (shouldSubscribeByName(_name.current, formState.name)) {
|
1783
|
+
control._stateFlags.mount = true;
|
1784
|
+
const fieldValues = control._getWatch(_name.current, defaultValue);
|
1785
|
+
updateValue(isObject(fieldValues)
|
1786
|
+
? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
|
1787
|
+
? [...fieldValues]
|
1788
|
+
: fieldValues);
|
1788
1789
|
}
|
1789
1790
|
},
|
1790
1791
|
});
|
@@ -1792,7 +1793,7 @@ function useWatch(props) {
|
|
1792
1793
|
? control._getWatch(name)
|
1793
1794
|
: defaultValue);
|
1794
1795
|
React.useEffect(() => {
|
1795
|
-
control.
|
1796
|
+
control._removeUnmounted();
|
1796
1797
|
});
|
1797
1798
|
return value;
|
1798
1799
|
}
|