react-hook-form 7.16.0 → 7.17.1
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 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +465 -469
- 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/getFocusFieldName.d.ts +1 -1
- package/dist/types/controller.d.ts +4 -2
- package/dist/types/form.d.ts +5 -6
- package/dist/types/utils.d.ts +4 -4
- package/dist/useSubscribe.d.ts +8 -0
- package/dist/utils/Subject.d.ts +2 -2
- package/package.json +17 -17
- package/CHANGELOG.md +0 -1133
- package/dist/logic/getMultipleSelectValue.d.ts +0 -2
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) {
|
@@ -104,10 +103,33 @@ var shouldRenderFormState = (formStateData, _proxyFormState, isRoot) => {
|
|
104
103
|
|
105
104
|
var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
|
106
105
|
|
106
|
+
function useSubscribe({ disabled, subject, callback }) {
|
107
|
+
const _subscription = React.useRef(subject);
|
108
|
+
const _unSubscribe = React.useRef();
|
109
|
+
if (disabled) {
|
110
|
+
if (_subscription.current) {
|
111
|
+
_unSubscribe.current && _unSubscribe.current.unsubscribe();
|
112
|
+
_subscription.current = _unSubscribe.current = undefined;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
else {
|
116
|
+
if (!_subscription.current) {
|
117
|
+
_subscription.current = subject;
|
118
|
+
}
|
119
|
+
if (!_unSubscribe.current && _subscription.current) {
|
120
|
+
_unSubscribe.current = _subscription.current.subscribe({
|
121
|
+
next: callback,
|
122
|
+
});
|
123
|
+
}
|
124
|
+
}
|
125
|
+
React.useEffect(() => () => {
|
126
|
+
_unSubscribe.current && _unSubscribe.current.unsubscribe();
|
127
|
+
}, []);
|
128
|
+
}
|
129
|
+
|
107
130
|
function useFormState(props) {
|
108
131
|
const methods = useFormContext();
|
109
132
|
const { control = methods.control, disabled, name } = props || {};
|
110
|
-
const nameRef = React.useRef(name);
|
111
133
|
const [formState, updateFormState] = React.useState(control._formState);
|
112
134
|
const _localProxyFormState = React.useRef({
|
113
135
|
isDirty: false,
|
@@ -117,18 +139,17 @@ function useFormState(props) {
|
|
117
139
|
isValid: false,
|
118
140
|
errors: false,
|
119
141
|
});
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
}, [disabled, control]);
|
142
|
+
const _name = React.useRef(name);
|
143
|
+
_name.current = name;
|
144
|
+
useSubscribe({
|
145
|
+
disabled,
|
146
|
+
callback: (formState) => (!_name.current ||
|
147
|
+
!formState.name ||
|
148
|
+
convertToArrayPayload(_name.current).includes(formState.name)) &&
|
149
|
+
shouldRenderFormState(formState, _localProxyFormState.current) &&
|
150
|
+
updateFormState(Object.assign(Object.assign({}, control._formState), formState)),
|
151
|
+
subject: control._subjects.state,
|
152
|
+
});
|
132
153
|
return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
|
133
154
|
}
|
134
155
|
|
@@ -140,6 +161,13 @@ function useController(props) {
|
|
140
161
|
control: control || methods.control,
|
141
162
|
name,
|
142
163
|
});
|
164
|
+
const _name = React.useRef(name);
|
165
|
+
_name.current = name;
|
166
|
+
useSubscribe({
|
167
|
+
subject: control._subjects.control,
|
168
|
+
callback: (data) => (!data.name || _name.current === data.name) &&
|
169
|
+
setInputStateValue(get(data.values, name)),
|
170
|
+
});
|
143
171
|
const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
|
144
172
|
const updateMounted = React.useCallback((name, value) => {
|
145
173
|
const field = get(control._fields, name);
|
@@ -148,14 +176,9 @@ function useController(props) {
|
|
148
176
|
}
|
149
177
|
}, [control]);
|
150
178
|
React.useEffect(() => {
|
151
|
-
const controllerSubscription = control._subjects.control.subscribe({
|
152
|
-
next: (data) => (!data.name || name === data.name) &&
|
153
|
-
setInputStateValue(get(data.values, name)),
|
154
|
-
});
|
155
179
|
updateMounted(name, true);
|
156
180
|
return () => {
|
157
|
-
|
158
|
-
const _shouldUnregisterField = control._shouldUnregister || shouldUnregister;
|
181
|
+
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
159
182
|
if (isNameInFieldArray(control._names.array, name)
|
160
183
|
? _shouldUnregisterField && !control._stateFlags.action
|
161
184
|
: _shouldUnregisterField) {
|
@@ -265,9 +288,10 @@ const focusFieldBy = (fields, callback, fieldsNames) => {
|
|
265
288
|
}
|
266
289
|
};
|
267
290
|
|
268
|
-
var getFocusFieldName = (name, index, options) => options
|
269
|
-
? options.focusName ||
|
270
|
-
|
291
|
+
var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
|
292
|
+
? options.focusName ||
|
293
|
+
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
294
|
+
: '';
|
271
295
|
|
272
296
|
var mapCurrentIds = (values, _fieldIds, keyName) => values.map((value, index) => {
|
273
297
|
const output = _fieldIds.current[index];
|
@@ -309,7 +333,7 @@ var moveArrayAt = (data, from, to) => {
|
|
309
333
|
return [];
|
310
334
|
};
|
311
335
|
|
312
|
-
var
|
336
|
+
var omitKeys = (fields, keyName) => fields.map((field = {}) => omit(field, keyName));
|
313
337
|
|
314
338
|
function prepend(data, value) {
|
315
339
|
return [...convertToArrayPayload(value), ...convertToArrayPayload(data)];
|
@@ -340,73 +364,81 @@ var updateAt = (fieldValues, index, value) => {
|
|
340
364
|
const useFieldArray = (props) => {
|
341
365
|
const methods = useFormContext();
|
342
366
|
const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
|
343
|
-
const [fields, setFields] = React.useState(mapIds(control.
|
367
|
+
const [fields, setFields] = React.useState(mapIds(control._getFieldArray(name), keyName));
|
344
368
|
const _fieldIds = React.useRef(fields);
|
345
369
|
_fieldIds.current = fields;
|
346
370
|
control._names.array.add(name);
|
371
|
+
useSubscribe({
|
372
|
+
callback: ({ values, name: fieldArrayName }) => {
|
373
|
+
if (fieldArrayName === name || !fieldArrayName) {
|
374
|
+
setFields(mapIds(get(values, name), keyName));
|
375
|
+
}
|
376
|
+
},
|
377
|
+
subject: control._subjects.array,
|
378
|
+
});
|
347
379
|
const updateValues = React.useCallback((updatedFieldArrayValuesWithKey) => {
|
348
|
-
const updatedFieldArrayValues =
|
380
|
+
const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
|
349
381
|
set(control._formValues, name, updatedFieldArrayValues);
|
350
382
|
setFields(updatedFieldArrayValuesWithKey);
|
351
383
|
return updatedFieldArrayValues;
|
352
384
|
}, [control, name, keyName]);
|
353
385
|
const append$1 = (value, options) => {
|
354
386
|
const appendValue = convertToArrayPayload(value);
|
355
|
-
const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control.
|
356
|
-
control._updateFieldArray(
|
387
|
+
const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(appendValue, keyName));
|
388
|
+
control._updateFieldArray(name, append, {
|
357
389
|
argA: fillEmptyArray(value),
|
358
390
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
359
391
|
control._names.focus = getFocusFieldName(name, updatedFieldArrayValuesWithKey.length - appendValue.length, options);
|
360
392
|
};
|
361
393
|
const prepend$1 = (value, options) => {
|
362
|
-
const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control.
|
363
|
-
control._updateFieldArray(
|
394
|
+
const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
|
395
|
+
control._updateFieldArray(name, prepend, {
|
364
396
|
argA: fillEmptyArray(value),
|
365
397
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
366
398
|
control._names.focus = getFocusFieldName(name, 0, options);
|
367
399
|
};
|
368
400
|
const remove = (index) => {
|
369
|
-
const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control.
|
370
|
-
control._updateFieldArray(
|
401
|
+
const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index);
|
402
|
+
control._updateFieldArray(name, removeArrayAt, {
|
371
403
|
argA: index,
|
372
404
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
373
405
|
};
|
374
406
|
const insert$1 = (index, value, options) => {
|
375
|
-
const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control.
|
376
|
-
control._updateFieldArray(
|
407
|
+
const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
|
408
|
+
control._updateFieldArray(name, insert, {
|
377
409
|
argA: index,
|
378
410
|
argB: fillEmptyArray(value),
|
379
411
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
380
412
|
control._names.focus = getFocusFieldName(name, index, options);
|
381
413
|
};
|
382
414
|
const swap = (indexA, indexB) => {
|
383
|
-
const updatedFieldArrayValuesWithKey = mapCurrentIds(control.
|
415
|
+
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
384
416
|
swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
|
385
|
-
control._updateFieldArray(
|
417
|
+
control._updateFieldArray(name, swapArrayAt, {
|
386
418
|
argA: indexA,
|
387
419
|
argB: indexB,
|
388
420
|
}, updateValues(updatedFieldArrayValuesWithKey), false);
|
389
421
|
};
|
390
422
|
const move = (from, to) => {
|
391
|
-
const updatedFieldArrayValuesWithKey = mapCurrentIds(control.
|
423
|
+
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
392
424
|
moveArrayAt(updatedFieldArrayValuesWithKey, from, to);
|
393
|
-
control._updateFieldArray(
|
425
|
+
control._updateFieldArray(name, moveArrayAt, {
|
394
426
|
argA: from,
|
395
427
|
argB: to,
|
396
428
|
}, updateValues(updatedFieldArrayValuesWithKey), false);
|
397
429
|
};
|
398
430
|
const update = (index, value) => {
|
399
|
-
const updatedFieldArrayValuesWithKey = mapCurrentIds(control.
|
431
|
+
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
400
432
|
const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
|
401
433
|
_fieldIds.current = mapIds(updatedFieldArrayValues, keyName);
|
402
|
-
control._updateFieldArray(
|
434
|
+
control._updateFieldArray(name, updateAt, {
|
403
435
|
argA: index,
|
404
436
|
argB: value,
|
405
437
|
}, updateValues(_fieldIds.current), true, false);
|
406
438
|
};
|
407
439
|
const replace = (value) => {
|
408
440
|
const updatedFieldArrayValuesWithKey = mapIds(convertToArrayPayload(value), keyName);
|
409
|
-
control._updateFieldArray(
|
441
|
+
control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
|
410
442
|
};
|
411
443
|
React.useEffect(() => {
|
412
444
|
control._stateFlags.action = false;
|
@@ -431,17 +463,9 @@ const useFieldArray = (props) => {
|
|
431
463
|
control._proxyFormState.isValid && control._updateValid();
|
432
464
|
}, [fields, name, control, keyName]);
|
433
465
|
React.useEffect(() => {
|
434
|
-
const fieldArraySubscription = control._subjects.array.subscribe({
|
435
|
-
next({ values, name: fieldArrayName }) {
|
436
|
-
if (fieldArrayName === name || !fieldArrayName) {
|
437
|
-
setFields(mapIds(get(values, name), keyName));
|
438
|
-
}
|
439
|
-
},
|
440
|
-
});
|
441
466
|
!get(control._formValues, name) && set(control._formValues, name, []);
|
442
467
|
return () => {
|
443
|
-
|
444
|
-
if (control._shouldUnregister || shouldUnregister) {
|
468
|
+
if (control._options.shouldUnregister || shouldUnregister) {
|
445
469
|
control.unregister(name);
|
446
470
|
}
|
447
471
|
};
|
@@ -483,12 +507,12 @@ function cloneObject(data) {
|
|
483
507
|
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
484
508
|
|
485
509
|
function deepEqual(object1, object2) {
|
486
|
-
if (isPrimitive(object1) ||
|
487
|
-
isPrimitive(object2) ||
|
488
|
-
isDateObject(object1) ||
|
489
|
-
isDateObject(object2)) {
|
510
|
+
if (isPrimitive(object1) || isPrimitive(object2)) {
|
490
511
|
return object1 === object2;
|
491
512
|
}
|
513
|
+
if (isDateObject(object1) && isDateObject(object2)) {
|
514
|
+
return object1.getTime() === object2.getTime();
|
515
|
+
}
|
492
516
|
const keys1 = Object.keys(object1);
|
493
517
|
const keys2 = Object.keys(object2);
|
494
518
|
if (keys1.length !== keys2.length) {
|
@@ -501,8 +525,9 @@ function deepEqual(object1, object2) {
|
|
501
525
|
}
|
502
526
|
if (key !== 'ref') {
|
503
527
|
const val2 = object2[key];
|
504
|
-
if ((
|
505
|
-
(isObject(
|
528
|
+
if ((isDateObject(val1) && isDateObject(val2)) ||
|
529
|
+
(isObject(val1) && isObject(val2)) ||
|
530
|
+
(Array.isArray(val1) && Array.isArray(val2))
|
506
531
|
? !deepEqual(val1, val2)
|
507
532
|
: val1 !== val2) {
|
508
533
|
return false;
|
@@ -522,8 +547,6 @@ var getValidationModes = (mode) => ({
|
|
522
547
|
|
523
548
|
var isBoolean = (value) => typeof value === 'boolean';
|
524
549
|
|
525
|
-
var isFileInput = (element) => element.type === 'file';
|
526
|
-
|
527
550
|
var isFunction = (value) => typeof value === 'function';
|
528
551
|
|
529
552
|
var isHTMLElement = (value) => value instanceof HTMLElement;
|
@@ -627,6 +650,8 @@ function unset(object, path) {
|
|
627
650
|
return object;
|
628
651
|
}
|
629
652
|
|
653
|
+
var isFileInput = (element) => element.type === 'file';
|
654
|
+
|
630
655
|
const defaultResult = {
|
631
656
|
value: false,
|
632
657
|
isValid: false,
|
@@ -664,10 +689,6 @@ var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isU
|
|
664
689
|
? setValueAs(value)
|
665
690
|
: value;
|
666
691
|
|
667
|
-
var getMultipleSelectValue = (options) => [...options]
|
668
|
-
.filter(({ selected }) => selected)
|
669
|
-
.map(({ value }) => value);
|
670
|
-
|
671
692
|
const defaultReturn = {
|
672
693
|
isValid: false,
|
673
694
|
value: null,
|
@@ -693,7 +714,7 @@ function getFieldValue(_f) {
|
|
693
714
|
return getRadioValue(_f.refs).value;
|
694
715
|
}
|
695
716
|
if (isMultipleSelect(ref)) {
|
696
|
-
return
|
717
|
+
return [...ref.selectedOptions].map(({ value }) => value);
|
697
718
|
}
|
698
719
|
if (isCheckBoxInput(ref)) {
|
699
720
|
return getCheckboxValue(_f.refs).value;
|
@@ -952,8 +973,7 @@ const defaultOptions = {
|
|
952
973
|
};
|
953
974
|
const isWindowUndefined = typeof window === 'undefined';
|
954
975
|
function createFormControl(props = {}) {
|
955
|
-
let
|
956
|
-
let _delayCallback;
|
976
|
+
let _options = Object.assign(Object.assign({}, defaultOptions), props);
|
957
977
|
let _formState = {
|
958
978
|
isDirty: false,
|
959
979
|
isValidating: false,
|
@@ -967,8 +987,8 @@ function createFormControl(props = {}) {
|
|
967
987
|
errors: {},
|
968
988
|
};
|
969
989
|
let _fields = {};
|
970
|
-
let _defaultValues =
|
971
|
-
let _formValues =
|
990
|
+
let _defaultValues = _options.defaultValues || {};
|
991
|
+
let _formValues = _options.shouldUnregister
|
972
992
|
? {}
|
973
993
|
: cloneObject(_defaultValues);
|
974
994
|
let _stateFlags = {
|
@@ -976,14 +996,15 @@ function createFormControl(props = {}) {
|
|
976
996
|
mount: false,
|
977
997
|
watch: false,
|
978
998
|
};
|
979
|
-
let _timer = 0;
|
980
999
|
let _names = {
|
981
1000
|
mount: new Set(),
|
982
1001
|
unMount: new Set(),
|
983
1002
|
array: new Set(),
|
984
1003
|
watch: new Set(),
|
985
1004
|
};
|
986
|
-
let
|
1005
|
+
let delayErrorCallback;
|
1006
|
+
let timer = 0;
|
1007
|
+
let validateFields = {};
|
987
1008
|
const _proxyFormState = {
|
988
1009
|
isDirty: false,
|
989
1010
|
dirtyFields: false,
|
@@ -998,37 +1019,125 @@ function createFormControl(props = {}) {
|
|
998
1019
|
array: new Subject(),
|
999
1020
|
state: new Subject(),
|
1000
1021
|
};
|
1001
|
-
const
|
1002
|
-
const
|
1003
|
-
const
|
1022
|
+
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
1023
|
+
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
1024
|
+
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
1004
1025
|
const debounce = (callback, wait) => (...args) => {
|
1005
|
-
clearTimeout(
|
1006
|
-
|
1026
|
+
clearTimeout(timer);
|
1027
|
+
timer = window.setTimeout(() => callback(...args), wait);
|
1007
1028
|
};
|
1008
|
-
const isFieldWatched = (name) =>
|
1009
|
-
_names.
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1029
|
+
const isFieldWatched = (name, isBlurEvent) => !isBlurEvent &&
|
1030
|
+
(_names.watchAll ||
|
1031
|
+
_names.watch.has(name) ||
|
1032
|
+
_names.watch.has((name.match(/\w+/) || [])[0]));
|
1033
|
+
const _updateValid = async (shouldSkipRender) => {
|
1034
|
+
let isValid = false;
|
1035
|
+
if (_proxyFormState.isValid) {
|
1036
|
+
isValid = _options.resolver
|
1037
|
+
? isEmptyObject((await executeResolver()).errors)
|
1038
|
+
: await executeBuildInValidation(_fields, true);
|
1039
|
+
if (!shouldSkipRender && isValid !== _formState.isValid) {
|
1040
|
+
_formState.isValid = isValid;
|
1041
|
+
_subjects.state.next({
|
1042
|
+
isValid,
|
1043
|
+
});
|
1044
|
+
}
|
1045
|
+
}
|
1046
|
+
return isValid;
|
1047
|
+
};
|
1048
|
+
const _updateFieldArray = (name, method, args, values = [], shouldSetValues = true, shouldSetFields = true) => {
|
1049
|
+
_stateFlags.action = true;
|
1050
|
+
if (shouldSetFields && get(_fields, name)) {
|
1051
|
+
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
1052
|
+
shouldSetValues && set(_fields, name, fieldValues);
|
1053
|
+
}
|
1054
|
+
if (Array.isArray(get(_formState.errors, name))) {
|
1055
|
+
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
1056
|
+
shouldSetValues && set(_formState.errors, name, errors);
|
1057
|
+
unsetEmptyArray(_formState.errors, name);
|
1058
|
+
}
|
1059
|
+
if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
|
1060
|
+
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
1061
|
+
shouldSetValues &&
|
1062
|
+
set(_formState.touchedFields, name, touchedFields);
|
1063
|
+
unsetEmptyArray(_formState.touchedFields, name);
|
1064
|
+
}
|
1065
|
+
if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
|
1066
|
+
updateFieldArrayDirty(name, values);
|
1067
|
+
}
|
1013
1068
|
_subjects.state.next({
|
1069
|
+
isDirty: _getDirty(name, values),
|
1070
|
+
dirtyFields: _formState.dirtyFields,
|
1014
1071
|
errors: _formState.errors,
|
1072
|
+
isValid: _formState.isValid,
|
1015
1073
|
});
|
1016
1074
|
};
|
1017
|
-
const
|
1018
|
-
|
1075
|
+
const updateErrors = (name, error) => (set(_formState.errors, name, error),
|
1076
|
+
_subjects.state.next({
|
1077
|
+
errors: _formState.errors,
|
1078
|
+
}));
|
1079
|
+
const updateValidAndValue = (name, shouldSkipSetValueAs, ref) => {
|
1080
|
+
const field = get(_fields, name);
|
1081
|
+
if (field) {
|
1082
|
+
const defaultValue = get(_formValues, name, get(_defaultValues, name));
|
1083
|
+
isUndefined(defaultValue) ||
|
1084
|
+
(ref && ref.defaultChecked) ||
|
1085
|
+
shouldSkipSetValueAs
|
1086
|
+
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
1087
|
+
: setFieldValue(name, defaultValue);
|
1088
|
+
}
|
1089
|
+
_stateFlags.mount && _updateValid();
|
1090
|
+
};
|
1091
|
+
const updateTouchAndDirty = (name, fieldValue, isCurrentTouched, shouldRender = true) => {
|
1092
|
+
let isFieldDirty = false;
|
1093
|
+
const output = {
|
1094
|
+
name,
|
1095
|
+
};
|
1096
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1097
|
+
if (_proxyFormState.isDirty) {
|
1098
|
+
const isPreviousFormDirty = _formState.isDirty;
|
1099
|
+
_formState.isDirty = output.isDirty = _getDirty();
|
1100
|
+
isFieldDirty = isPreviousFormDirty !== output.isDirty;
|
1101
|
+
}
|
1102
|
+
if (_proxyFormState.dirtyFields && !isCurrentTouched) {
|
1103
|
+
const isPreviousFieldDirty = get(_formState.dirtyFields, name);
|
1104
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
1105
|
+
isCurrentFieldPristine
|
1106
|
+
? unset(_formState.dirtyFields, name)
|
1107
|
+
: set(_formState.dirtyFields, name, true);
|
1108
|
+
output.dirtyFields = _formState.dirtyFields;
|
1109
|
+
isFieldDirty =
|
1110
|
+
isFieldDirty ||
|
1111
|
+
isPreviousFieldDirty !== get(_formState.dirtyFields, name);
|
1112
|
+
}
|
1113
|
+
if (isCurrentTouched && !isPreviousFieldTouched) {
|
1114
|
+
set(_formState.touchedFields, name, isCurrentTouched);
|
1115
|
+
output.touchedFields = _formState.touchedFields;
|
1116
|
+
isFieldDirty =
|
1117
|
+
isFieldDirty ||
|
1118
|
+
(_proxyFormState.touchedFields &&
|
1119
|
+
isPreviousFieldTouched !== isCurrentTouched);
|
1120
|
+
}
|
1121
|
+
isFieldDirty && shouldRender && _subjects.state.next(output);
|
1122
|
+
return isFieldDirty ? output : {};
|
1123
|
+
};
|
1124
|
+
const updateFieldArrayDirty = (name, value) => (set(_formState.dirtyFields, name, setFieldArrayDirtyFields(value, get(_defaultValues, name, []), get(_formState.dirtyFields, name, []))),
|
1125
|
+
unsetEmptyArray(_formState.dirtyFields, name));
|
1126
|
+
const shouldRenderByError = async (shouldSkipRender, name, isValid, error, fieldState) => {
|
1127
|
+
const previousFieldError = get(_formState.errors, name);
|
1019
1128
|
const shouldUpdateValid = _proxyFormState.isValid && _formState.isValid !== isValid;
|
1020
1129
|
if (props.delayError && error) {
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1130
|
+
delayErrorCallback =
|
1131
|
+
delayErrorCallback || debounce(updateErrors, props.delayError);
|
1132
|
+
delayErrorCallback(name, error);
|
1024
1133
|
}
|
1025
1134
|
else {
|
1026
|
-
clearTimeout(
|
1135
|
+
clearTimeout(timer);
|
1027
1136
|
error
|
1028
1137
|
? set(_formState.errors, name, error)
|
1029
1138
|
: unset(_formState.errors, name);
|
1030
1139
|
}
|
1031
|
-
if (((error ? !deepEqual(
|
1140
|
+
if (((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
1032
1141
|
!isEmptyObject(fieldState) ||
|
1033
1142
|
shouldUpdateValid) &&
|
1034
1143
|
!shouldSkipRender) {
|
@@ -1036,138 +1145,169 @@ function createFormControl(props = {}) {
|
|
1036
1145
|
_formState = Object.assign(Object.assign({}, _formState), updatedFormState);
|
1037
1146
|
_subjects.state.next(updatedFormState);
|
1038
1147
|
}
|
1039
|
-
|
1040
|
-
if (_proxyFormState.isValidating && !
|
1148
|
+
validateFields[name]--;
|
1149
|
+
if (_proxyFormState.isValidating && !validateFields[name]) {
|
1041
1150
|
_subjects.state.next({
|
1042
1151
|
isValidating: false,
|
1043
1152
|
});
|
1044
|
-
|
1153
|
+
validateFields = {};
|
1045
1154
|
}
|
1046
1155
|
};
|
1156
|
+
const executeResolver = async (name) => _options.resolver
|
1157
|
+
? await _options.resolver(Object.assign({}, _formValues), _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation))
|
1158
|
+
: {};
|
1159
|
+
const executeResolverValidation = async (names) => {
|
1160
|
+
const { errors } = await executeResolver();
|
1161
|
+
if (names) {
|
1162
|
+
for (const name of names) {
|
1163
|
+
const error = get(errors, name);
|
1164
|
+
error
|
1165
|
+
? set(_formState.errors, name, error)
|
1166
|
+
: unset(_formState.errors, name);
|
1167
|
+
}
|
1168
|
+
}
|
1169
|
+
else {
|
1170
|
+
_formState.errors = errors;
|
1171
|
+
}
|
1172
|
+
return errors;
|
1173
|
+
};
|
1174
|
+
const executeBuildInValidation = async (fields, shouldOnlyCheckValid, context = {
|
1175
|
+
valid: true,
|
1176
|
+
}) => {
|
1177
|
+
for (const name in fields) {
|
1178
|
+
const field = fields[name];
|
1179
|
+
if (field) {
|
1180
|
+
const fieldReference = field._f;
|
1181
|
+
const fieldValue = omit(field, '_f');
|
1182
|
+
if (fieldReference) {
|
1183
|
+
const fieldError = await validateField(field, get(_formValues, fieldReference.name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation);
|
1184
|
+
if (fieldError[fieldReference.name]) {
|
1185
|
+
context.valid = false;
|
1186
|
+
if (shouldOnlyCheckValid) {
|
1187
|
+
break;
|
1188
|
+
}
|
1189
|
+
}
|
1190
|
+
if (!shouldOnlyCheckValid) {
|
1191
|
+
fieldError[fieldReference.name]
|
1192
|
+
? set(_formState.errors, fieldReference.name, fieldError[fieldReference.name])
|
1193
|
+
: unset(_formState.errors, fieldReference.name);
|
1194
|
+
}
|
1195
|
+
}
|
1196
|
+
fieldValue &&
|
1197
|
+
(await executeBuildInValidation(fieldValue, shouldOnlyCheckValid, context));
|
1198
|
+
}
|
1199
|
+
}
|
1200
|
+
return context.valid;
|
1201
|
+
};
|
1202
|
+
const _removeUnmounted = () => {
|
1203
|
+
for (const name of _names.unMount) {
|
1204
|
+
const field = get(_fields, name);
|
1205
|
+
field &&
|
1206
|
+
(field._f.refs ? field._f.refs.every(live) : live(field._f.ref)) &&
|
1207
|
+
unregister(name);
|
1208
|
+
}
|
1209
|
+
_names.unMount = new Set();
|
1210
|
+
};
|
1211
|
+
const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
|
1212
|
+
!deepEqual(getValues(), _defaultValues));
|
1213
|
+
const _getWatch = (names, defaultValue, isGlobal) => {
|
1214
|
+
const fieldValues = Object.assign({}, (_stateFlags.mount
|
1215
|
+
? _formValues
|
1216
|
+
: isUndefined(defaultValue)
|
1217
|
+
? _defaultValues
|
1218
|
+
: isString(names)
|
1219
|
+
? { [names]: defaultValue }
|
1220
|
+
: defaultValue));
|
1221
|
+
if (names) {
|
1222
|
+
const result = convertToArrayPayload(names).map((fieldName) => (isGlobal && _names.watch.add(fieldName),
|
1223
|
+
get(fieldValues, fieldName)));
|
1224
|
+
return Array.isArray(names) ? result : result[0];
|
1225
|
+
}
|
1226
|
+
isGlobal && (_names.watchAll = true);
|
1227
|
+
return fieldValues;
|
1228
|
+
};
|
1229
|
+
const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, []);
|
1047
1230
|
const setFieldValue = (name, value, options = {}, shouldRender) => {
|
1048
1231
|
const field = get(_fields, name);
|
1049
1232
|
let fieldValue = value;
|
1050
1233
|
if (field) {
|
1051
|
-
const
|
1052
|
-
if (
|
1053
|
-
set(_formValues, name, getFieldValueAs(value,
|
1234
|
+
const fieldReference = field._f;
|
1235
|
+
if (fieldReference) {
|
1236
|
+
set(_formValues, name, getFieldValueAs(value, fieldReference));
|
1054
1237
|
fieldValue =
|
1055
|
-
isWeb && isHTMLElement(
|
1238
|
+
isWeb && isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
|
1056
1239
|
? ''
|
1057
1240
|
: value;
|
1058
|
-
if (
|
1059
|
-
|
1060
|
-
}
|
1061
|
-
else if (isMultipleSelect(_f.ref)) {
|
1062
|
-
[..._f.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
|
1241
|
+
if (isMultipleSelect(fieldReference.ref)) {
|
1242
|
+
[...fieldReference.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
|
1063
1243
|
}
|
1064
|
-
else if (
|
1065
|
-
if (isCheckBoxInput(
|
1066
|
-
|
1067
|
-
?
|
1244
|
+
else if (fieldReference.refs) {
|
1245
|
+
if (isCheckBoxInput(fieldReference.ref)) {
|
1246
|
+
fieldReference.refs.length > 1
|
1247
|
+
? fieldReference.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(fieldValue)
|
1068
1248
|
? !!fieldValue.find((data) => data === checkboxRef.value)
|
1069
1249
|
: fieldValue === checkboxRef.value))
|
1070
|
-
: (
|
1250
|
+
: (fieldReference.refs[0].checked = !!fieldValue);
|
1071
1251
|
}
|
1072
1252
|
else {
|
1073
|
-
|
1253
|
+
fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
|
1074
1254
|
}
|
1075
1255
|
}
|
1076
1256
|
else {
|
1077
|
-
|
1257
|
+
fieldReference.ref.value = fieldValue;
|
1078
1258
|
}
|
1079
|
-
|
1259
|
+
shouldRender &&
|
1080
1260
|
_subjects.control.next({
|
1081
1261
|
values: _formValues,
|
1082
1262
|
name,
|
1083
1263
|
});
|
1084
|
-
}
|
1085
1264
|
}
|
1086
1265
|
}
|
1087
1266
|
(options.shouldDirty || options.shouldTouch) &&
|
1088
|
-
|
1267
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch);
|
1089
1268
|
options.shouldValidate && trigger(name);
|
1090
1269
|
};
|
1091
|
-
const
|
1092
|
-
const
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
if (_proxyFormState.dirtyFields && !isCurrentTouched) {
|
1103
|
-
const isPreviousFieldDirty = get(_formState.dirtyFields, name);
|
1104
|
-
const isCurrentFieldDirty = !deepEqual(get(_defaultValues, name), inputValue);
|
1105
|
-
isCurrentFieldDirty
|
1106
|
-
? set(_formState.dirtyFields, name, true)
|
1107
|
-
: unset(_formState.dirtyFields, name);
|
1108
|
-
state.dirtyFields = _formState.dirtyFields;
|
1109
|
-
isChanged =
|
1110
|
-
isChanged || isPreviousFieldDirty !== get(_formState.dirtyFields, name);
|
1111
|
-
}
|
1112
|
-
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1113
|
-
if (isCurrentTouched && !isPreviousFieldTouched) {
|
1114
|
-
set(_formState.touchedFields, name, isCurrentTouched);
|
1115
|
-
state.touchedFields = _formState.touchedFields;
|
1116
|
-
isChanged =
|
1117
|
-
isChanged ||
|
1118
|
-
(_proxyFormState.touchedFields &&
|
1119
|
-
isPreviousFieldTouched !== isCurrentTouched);
|
1270
|
+
const setValues = (name, value, options) => {
|
1271
|
+
for (const fieldKey in value) {
|
1272
|
+
const fieldValue = value[fieldKey];
|
1273
|
+
const fieldName = `${name}.${fieldKey}`;
|
1274
|
+
const field = get(_fields, fieldName);
|
1275
|
+
(_names.array.has(name) ||
|
1276
|
+
!isPrimitive(fieldValue) ||
|
1277
|
+
(field && !field._f)) &&
|
1278
|
+
!isDateObject(fieldValue)
|
1279
|
+
? setValues(fieldName, fieldValue, options)
|
1280
|
+
: setFieldValue(fieldName, fieldValue, options, true);
|
1120
1281
|
}
|
1121
|
-
isChanged && shouldRender && _subjects.state.next(state);
|
1122
|
-
return isChanged ? state : {};
|
1123
1282
|
};
|
1124
|
-
const
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1283
|
+
const setValue = (name, value, options = {}) => {
|
1284
|
+
const field = get(_fields, name);
|
1285
|
+
const isFieldArray = _names.array.has(name);
|
1286
|
+
set(_formValues, name, value);
|
1287
|
+
if (isFieldArray) {
|
1288
|
+
_subjects.array.next({
|
1289
|
+
name,
|
1290
|
+
values: _formValues,
|
1291
|
+
});
|
1292
|
+
if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) &&
|
1293
|
+
options.shouldDirty) {
|
1294
|
+
updateFieldArrayDirty(name, value);
|
1295
|
+
_subjects.state.next({
|
1296
|
+
name,
|
1297
|
+
dirtyFields: _formState.dirtyFields,
|
1298
|
+
isDirty: _getDirty(name, value),
|
1299
|
+
});
|
1137
1300
|
}
|
1138
1301
|
}
|
1139
1302
|
else {
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
};
|
1144
|
-
const validateForm = async (_fields, shouldCheckValid, context = {
|
1145
|
-
valid: true,
|
1146
|
-
}) => {
|
1147
|
-
for (const name in _fields) {
|
1148
|
-
const field = _fields[name];
|
1149
|
-
if (field) {
|
1150
|
-
const _f = field._f;
|
1151
|
-
const fieldValue = omit(field, '_f');
|
1152
|
-
if (_f) {
|
1153
|
-
const fieldError = await validateField(field, get(_formValues, _f.name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation);
|
1154
|
-
if (fieldError[_f.name]) {
|
1155
|
-
context.valid = false;
|
1156
|
-
if (shouldCheckValid) {
|
1157
|
-
break;
|
1158
|
-
}
|
1159
|
-
}
|
1160
|
-
if (!shouldCheckValid) {
|
1161
|
-
fieldError[_f.name]
|
1162
|
-
? set(_formState.errors, _f.name, fieldError[_f.name])
|
1163
|
-
: unset(_formState.errors, _f.name);
|
1164
|
-
}
|
1165
|
-
}
|
1166
|
-
fieldValue &&
|
1167
|
-
(await validateForm(fieldValue, shouldCheckValid, context));
|
1168
|
-
}
|
1303
|
+
field && !field._f && !isNullOrUndefined(value)
|
1304
|
+
? setValues(name, value, options)
|
1305
|
+
: setFieldValue(name, value, options, true);
|
1169
1306
|
}
|
1170
|
-
|
1307
|
+
isFieldWatched(name) && _subjects.state.next({});
|
1308
|
+
_subjects.watch.next({
|
1309
|
+
name,
|
1310
|
+
});
|
1171
1311
|
};
|
1172
1312
|
const handleChange = async (event) => {
|
1173
1313
|
const target = event.target;
|
@@ -1176,22 +1316,22 @@ function createFormControl(props = {}) {
|
|
1176
1316
|
if (field) {
|
1177
1317
|
let error;
|
1178
1318
|
let isValid;
|
1179
|
-
const
|
1319
|
+
const fieldValue = target.type ? getFieldValue(field._f) : target.value;
|
1180
1320
|
const isBlurEvent = event.type === EVENTS.BLUR;
|
1321
|
+
const shouldSkipValidation = (!hasValidation(field._f) &&
|
1322
|
+
!_options.resolver &&
|
1323
|
+
!get(_formState.errors, name) &&
|
1324
|
+
!field._f.deps) ||
|
1325
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
|
1326
|
+
const isWatched = isFieldWatched(name, isBlurEvent);
|
1181
1327
|
if (isBlurEvent && field._f.onBlur) {
|
1182
1328
|
field._f.onBlur(event);
|
1183
1329
|
}
|
1184
1330
|
else if (field._f.onChange) {
|
1185
1331
|
field._f.onChange(event);
|
1186
1332
|
}
|
1187
|
-
|
1188
|
-
|
1189
|
-
!get(_formState.errors, name) &&
|
1190
|
-
!field._f.deps) ||
|
1191
|
-
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, reValidateMode, validationMode);
|
1192
|
-
const isWatched = !isBlurEvent && isFieldWatched(name);
|
1193
|
-
set(_formValues, name, inputValue);
|
1194
|
-
const fieldState = updateTouchAndDirtyState(name, inputValue, isBlurEvent, false);
|
1333
|
+
set(_formValues, name, fieldValue);
|
1334
|
+
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
|
1195
1335
|
const shouldRender = !isEmptyObject(fieldState) || isWatched;
|
1196
1336
|
!isBlurEvent &&
|
1197
1337
|
_subjects.watch.next({
|
@@ -1203,12 +1343,12 @@ function createFormControl(props = {}) {
|
|
1203
1343
|
_subjects.state.next(Object.assign({ name }, (isWatched ? {} : fieldState))));
|
1204
1344
|
}
|
1205
1345
|
!isBlurEvent && isWatched && _subjects.state.next({});
|
1206
|
-
|
1346
|
+
validateFields[name] = validateFields[name] ? +1 : 1;
|
1207
1347
|
_proxyFormState.isValidating &&
|
1208
1348
|
_subjects.state.next({
|
1209
1349
|
isValidating: true,
|
1210
1350
|
});
|
1211
|
-
if (
|
1351
|
+
if (_options.resolver) {
|
1212
1352
|
const { errors } = await executeResolver([name]);
|
1213
1353
|
error = get(errors, name);
|
1214
1354
|
if (isCheckBoxInput(target) && !error) {
|
@@ -1224,170 +1364,42 @@ function createFormControl(props = {}) {
|
|
1224
1364
|
isValid = isEmptyObject(errors);
|
1225
1365
|
}
|
1226
1366
|
else {
|
1227
|
-
error = (await validateField(field, get(_formValues, name),
|
1367
|
+
error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
|
1228
1368
|
isValid = await _updateValid(true);
|
1229
1369
|
}
|
1230
|
-
|
1231
|
-
|
1232
|
-
}
|
1233
|
-
shouldRenderBaseOnError(false, name, isValid, error, fieldState);
|
1234
|
-
}
|
1235
|
-
};
|
1236
|
-
const _updateValidAndInputValue = (name, shouldSkipValueAs, ref) => {
|
1237
|
-
const field = get(_fields, name);
|
1238
|
-
if (field) {
|
1239
|
-
const fieldValue = get(_formValues, name);
|
1240
|
-
const defaultValue = isUndefined(fieldValue)
|
1241
|
-
? get(_defaultValues, name)
|
1242
|
-
: fieldValue;
|
1243
|
-
if (isUndefined(defaultValue) ||
|
1244
|
-
(ref && ref.defaultChecked) ||
|
1245
|
-
shouldSkipValueAs) {
|
1246
|
-
set(_formValues, name, shouldSkipValueAs ? defaultValue : getFieldValue(field._f));
|
1247
|
-
}
|
1248
|
-
else {
|
1249
|
-
setFieldValue(name, defaultValue);
|
1250
|
-
}
|
1251
|
-
}
|
1252
|
-
_stateFlags.mount && _updateValid();
|
1253
|
-
};
|
1254
|
-
const _getIsDirty = (name, data) => {
|
1255
|
-
name && data && set(_formValues, name, data);
|
1256
|
-
return !deepEqual(Object.assign({}, getValues()), _defaultValues);
|
1257
|
-
};
|
1258
|
-
const _updateValid = async (skipRender) => {
|
1259
|
-
let isValid = false;
|
1260
|
-
if (_proxyFormState.isValid) {
|
1261
|
-
isValid = formOptions.resolver
|
1262
|
-
? isEmptyObject((await executeResolver()).errors)
|
1263
|
-
: await validateForm(_fields, true);
|
1264
|
-
if (!skipRender && isValid !== _formState.isValid) {
|
1265
|
-
_formState.isValid = isValid;
|
1266
|
-
_subjects.state.next({
|
1267
|
-
isValid,
|
1268
|
-
});
|
1269
|
-
}
|
1270
|
-
}
|
1271
|
-
return isValid;
|
1272
|
-
};
|
1273
|
-
const setValues = (name, value, options) => Object.entries(value).forEach(([fieldKey, fieldValue]) => {
|
1274
|
-
const fieldName = `${name}.${fieldKey}`;
|
1275
|
-
const field = get(_fields, fieldName);
|
1276
|
-
(_names.array.has(name) ||
|
1277
|
-
!isPrimitive(fieldValue) ||
|
1278
|
-
(field && !field._f)) &&
|
1279
|
-
!isDateObject(fieldValue)
|
1280
|
-
? setValues(fieldName, fieldValue, options)
|
1281
|
-
: setFieldValue(fieldName, fieldValue, options, true);
|
1282
|
-
});
|
1283
|
-
const _getWatch = (fieldNames, defaultValue, isMounted, isGlobal) => {
|
1284
|
-
const fieldValues = Object.assign({}, (isMounted || _stateFlags.mount
|
1285
|
-
? _formValues
|
1286
|
-
: isUndefined(defaultValue)
|
1287
|
-
? _defaultValues
|
1288
|
-
: isString(fieldNames)
|
1289
|
-
? { [fieldNames]: defaultValue }
|
1290
|
-
: defaultValue));
|
1291
|
-
if (!fieldNames) {
|
1292
|
-
isGlobal && (_names.watchAll = true);
|
1293
|
-
return fieldValues;
|
1294
|
-
}
|
1295
|
-
const result = [];
|
1296
|
-
for (const fieldName of convertToArrayPayload(fieldNames)) {
|
1297
|
-
isGlobal && _names.watch.add(fieldName);
|
1298
|
-
result.push(get(fieldValues, fieldName));
|
1299
|
-
}
|
1300
|
-
return Array.isArray(fieldNames) ? result : result[0];
|
1301
|
-
};
|
1302
|
-
const _updateFieldArray = (keyName, name, method, args, values = [], shouldSet = true, shouldSetFields = true) => {
|
1303
|
-
let output;
|
1304
|
-
_stateFlags.action = true;
|
1305
|
-
if (shouldSetFields && get(_fields, name)) {
|
1306
|
-
output = method(get(_fields, name), args.argA, args.argB);
|
1307
|
-
shouldSet && set(_fields, name, output);
|
1308
|
-
}
|
1309
|
-
if (Array.isArray(get(_formState.errors, name))) {
|
1310
|
-
const output = method(get(_formState.errors, name), args.argA, args.argB);
|
1311
|
-
shouldSet && set(_formState.errors, name, output);
|
1312
|
-
unsetEmptyArray(_formState.errors, name);
|
1313
|
-
}
|
1314
|
-
if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
|
1315
|
-
const output = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
1316
|
-
shouldSet && set(_formState.touchedFields, name, output);
|
1317
|
-
unsetEmptyArray(_formState.touchedFields, name);
|
1318
|
-
}
|
1319
|
-
if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
|
1320
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(values, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1321
|
-
values &&
|
1322
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(values, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1323
|
-
unsetEmptyArray(_formState.dirtyFields, name);
|
1324
|
-
}
|
1325
|
-
_subjects.state.next({
|
1326
|
-
isDirty: _getIsDirty(name, omitKey(values, keyName)),
|
1327
|
-
dirtyFields: _formState.dirtyFields,
|
1328
|
-
errors: _formState.errors,
|
1329
|
-
isValid: _formState.isValid,
|
1330
|
-
});
|
1331
|
-
};
|
1332
|
-
const _getFieldArrayValue = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, []);
|
1333
|
-
const setValue = (name, value, options = {}) => {
|
1334
|
-
const field = get(_fields, name);
|
1335
|
-
const isFieldArray = _names.array.has(name);
|
1336
|
-
set(_formValues, name, value);
|
1337
|
-
if (isFieldArray) {
|
1338
|
-
_subjects.array.next({
|
1339
|
-
name,
|
1340
|
-
values: _formValues,
|
1341
|
-
});
|
1342
|
-
if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) &&
|
1343
|
-
options.shouldDirty) {
|
1344
|
-
set(_formState.dirtyFields, name, setFieldArrayDirtyFields(value, get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
|
1345
|
-
_subjects.state.next({
|
1346
|
-
name,
|
1347
|
-
dirtyFields: _formState.dirtyFields,
|
1348
|
-
isDirty: _getIsDirty(name, value),
|
1349
|
-
});
|
1350
|
-
}
|
1370
|
+
field._f.deps && trigger(field._f.deps);
|
1371
|
+
shouldRenderByError(false, name, isValid, error, fieldState);
|
1351
1372
|
}
|
1352
|
-
else {
|
1353
|
-
field && !field._f && !isNullOrUndefined(value)
|
1354
|
-
? setValues(name, value, options)
|
1355
|
-
: setFieldValue(name, value, options, true);
|
1356
|
-
}
|
1357
|
-
isFieldWatched(name) && _subjects.state.next({});
|
1358
|
-
_subjects.watch.next({
|
1359
|
-
name,
|
1360
|
-
});
|
1361
1373
|
};
|
1362
1374
|
const trigger = async (name, options = {}) => {
|
1363
|
-
const fieldNames = convertToArrayPayload(name);
|
1364
1375
|
let isValid;
|
1376
|
+
let validationResult;
|
1377
|
+
const fieldNames = convertToArrayPayload(name);
|
1365
1378
|
_subjects.state.next({
|
1366
1379
|
isValidating: true,
|
1367
1380
|
});
|
1368
|
-
if (
|
1369
|
-
const
|
1370
|
-
isValid =
|
1371
|
-
|
1372
|
-
|
1381
|
+
if (_options.resolver) {
|
1382
|
+
const errors = await executeResolverValidation(isUndefined(name) ? name : fieldNames);
|
1383
|
+
isValid = isEmptyObject(errors);
|
1384
|
+
validationResult = name
|
1385
|
+
? !fieldNames.some((name) => get(errors, name))
|
1386
|
+
: isValid;
|
1387
|
+
}
|
1388
|
+
else if (name) {
|
1389
|
+
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
|
1390
|
+
const field = get(_fields, fieldName);
|
1391
|
+
return await executeBuildInValidation(field && field._f ? { [fieldName]: field } : field);
|
1392
|
+
}))).every(Boolean);
|
1393
|
+
_updateValid();
|
1373
1394
|
}
|
1374
1395
|
else {
|
1375
|
-
|
1376
|
-
isValid = (await Promise.all(fieldNames.map(async (fieldName) => {
|
1377
|
-
const field = get(_fields, fieldName);
|
1378
|
-
return await validateForm(field && field._f ? { [fieldName]: field } : field);
|
1379
|
-
}))).every(Boolean);
|
1380
|
-
_updateValid();
|
1381
|
-
}
|
1382
|
-
else {
|
1383
|
-
isValid = await validateForm(_fields);
|
1384
|
-
}
|
1396
|
+
validationResult = isValid = await executeBuildInValidation(_fields);
|
1385
1397
|
}
|
1386
|
-
_subjects.state.next(Object.assign(Object.assign({}, (isString(name) ? {
|
1387
|
-
|
1398
|
+
_subjects.state.next(Object.assign(Object.assign({}, (!isString(name) || isValid !== _formState.isValid ? {} : { name })), { errors: _formState.errors, isValid, isValidating: false }));
|
1399
|
+
options.shouldFocus &&
|
1400
|
+
!validationResult &&
|
1388
1401
|
focusFieldBy(_fields, (key) => get(_formState.errors, key), name ? fieldNames : _names.mount);
|
1389
|
-
|
1390
|
-
return isValid;
|
1402
|
+
return validationResult;
|
1391
1403
|
};
|
1392
1404
|
const getValues = (fieldNames) => {
|
1393
1405
|
const values = Object.assign(Object.assign({}, _defaultValues), (_stateFlags.mount ? _formValues : {}));
|
@@ -1415,88 +1427,83 @@ function createFormControl(props = {}) {
|
|
1415
1427
|
});
|
1416
1428
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
1417
1429
|
};
|
1418
|
-
const watch = (
|
1430
|
+
const watch = (name, defaultValue) => isFunction(name)
|
1419
1431
|
? _subjects.watch.subscribe({
|
1420
|
-
next: (info) =>
|
1432
|
+
next: (info) => name(_getWatch(undefined, defaultValue), info),
|
1421
1433
|
})
|
1422
|
-
: _getWatch(
|
1434
|
+
: _getWatch(name, defaultValue, true);
|
1423
1435
|
const unregister = (name, options = {}) => {
|
1424
|
-
for (const
|
1425
|
-
_names.mount.delete(
|
1426
|
-
_names.array.delete(
|
1427
|
-
if (get(_fields,
|
1436
|
+
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
1437
|
+
_names.mount.delete(fieldName);
|
1438
|
+
_names.array.delete(fieldName);
|
1439
|
+
if (get(_fields, fieldName)) {
|
1428
1440
|
if (!options.keepValue) {
|
1429
|
-
unset(_fields,
|
1430
|
-
unset(_formValues,
|
1441
|
+
unset(_fields, fieldName);
|
1442
|
+
unset(_formValues, fieldName);
|
1431
1443
|
}
|
1432
|
-
!options.keepError && unset(_formState.errors,
|
1433
|
-
!options.keepDirty && unset(_formState.dirtyFields,
|
1434
|
-
!options.keepTouched && unset(_formState.touchedFields,
|
1435
|
-
!
|
1444
|
+
!options.keepError && unset(_formState.errors, fieldName);
|
1445
|
+
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
1446
|
+
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
1447
|
+
!_options.shouldUnregister &&
|
1436
1448
|
!options.keepDefaultValue &&
|
1437
|
-
unset(_defaultValues,
|
1449
|
+
unset(_defaultValues, fieldName);
|
1438
1450
|
}
|
1439
1451
|
}
|
1440
1452
|
_subjects.watch.next({});
|
1441
|
-
_subjects.state.next(Object.assign(Object.assign({}, _formState), (!options.keepDirty ? {} : { isDirty:
|
1453
|
+
_subjects.state.next(Object.assign(Object.assign({}, _formState), (!options.keepDirty ? {} : { isDirty: _getDirty() })));
|
1442
1454
|
!options.keepIsValid && _updateValid();
|
1443
1455
|
};
|
1444
|
-
const registerFieldRef = (name, fieldRef, options) => {
|
1445
|
-
register(name, options);
|
1446
|
-
let field = get(_fields, name);
|
1447
|
-
const ref = isUndefined(fieldRef.value)
|
1448
|
-
? fieldRef.querySelectorAll
|
1449
|
-
? fieldRef.querySelectorAll('input,select,textarea')[0] ||
|
1450
|
-
fieldRef
|
1451
|
-
: fieldRef
|
1452
|
-
: fieldRef;
|
1453
|
-
const isRadioOrCheckbox = isRadioOrCheckboxFunction(ref);
|
1454
|
-
if (ref === field._f.ref ||
|
1455
|
-
(isRadioOrCheckbox &&
|
1456
|
-
compact(field._f.refs || []).find((option) => option === ref))) {
|
1457
|
-
return;
|
1458
|
-
}
|
1459
|
-
field = {
|
1460
|
-
_f: isRadioOrCheckbox
|
1461
|
-
? Object.assign(Object.assign({}, field._f), { refs: [
|
1462
|
-
...compact(field._f.refs || []).filter((ref) => isHTMLElement(ref) && document.contains(ref)),
|
1463
|
-
ref,
|
1464
|
-
], ref: { type: ref.type, name } }) : Object.assign(Object.assign({}, field._f), { ref }),
|
1465
|
-
};
|
1466
|
-
set(_fields, name, field);
|
1467
|
-
(!options || !options.disabled) &&
|
1468
|
-
_updateValidAndInputValue(name, false, ref);
|
1469
|
-
};
|
1470
1456
|
const register = (name, options = {}) => {
|
1471
1457
|
const field = get(_fields, name);
|
1472
1458
|
set(_fields, name, {
|
1473
1459
|
_f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
|
1474
1460
|
});
|
1475
1461
|
_names.mount.add(name);
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
}
|
1484
|
-
!field && _updateValidAndInputValue(name, true);
|
1462
|
+
!isUndefined(options.value) && set(_formValues, name, options.value);
|
1463
|
+
field
|
1464
|
+
? isBoolean(options.disabled) &&
|
1465
|
+
set(_formValues, name, options.disabled
|
1466
|
+
? undefined
|
1467
|
+
: get(_formValues, name, getFieldValue(field._f)))
|
1468
|
+
: updateValidAndValue(name, true);
|
1485
1469
|
return isWindowUndefined
|
1486
1470
|
? { name: name }
|
1487
1471
|
: Object.assign(Object.assign({ name }, (isBoolean(options.disabled)
|
1488
1472
|
? { disabled: options.disabled }
|
1489
1473
|
: {})), { onChange: handleChange, onBlur: handleChange, ref: (ref) => {
|
1490
1474
|
if (ref) {
|
1491
|
-
|
1475
|
+
register(name, options);
|
1476
|
+
let field = get(_fields, name);
|
1477
|
+
const fieldRef = isUndefined(ref.value)
|
1478
|
+
? ref.querySelectorAll
|
1479
|
+
? ref.querySelectorAll('input,select,textarea')[0] ||
|
1480
|
+
ref
|
1481
|
+
: ref
|
1482
|
+
: ref;
|
1483
|
+
const isRadioOrCheckbox = isRadioOrCheckboxFunction(fieldRef);
|
1484
|
+
if (fieldRef === field._f.ref ||
|
1485
|
+
(isRadioOrCheckbox &&
|
1486
|
+
compact(field._f.refs || []).find((option) => option === fieldRef))) {
|
1487
|
+
return;
|
1488
|
+
}
|
1489
|
+
field = {
|
1490
|
+
_f: isRadioOrCheckbox
|
1491
|
+
? Object.assign(Object.assign({}, field._f), { refs: [
|
1492
|
+
...compact(field._f.refs || []).filter((ref) => isHTMLElement(ref) && document.contains(ref)),
|
1493
|
+
fieldRef,
|
1494
|
+
], ref: { type: fieldRef.type, name } }) : Object.assign(Object.assign({}, field._f), { ref: fieldRef }),
|
1495
|
+
};
|
1496
|
+
set(_fields, name, field);
|
1497
|
+
(!options || !options.disabled) &&
|
1498
|
+
updateValidAndValue(name, false, fieldRef);
|
1492
1499
|
}
|
1493
1500
|
else {
|
1494
1501
|
const field = get(_fields, name, {});
|
1495
|
-
const
|
1502
|
+
const shouldUnregister = _options.shouldUnregister || options.shouldUnregister;
|
1496
1503
|
if (field._f) {
|
1497
1504
|
field._f.mount = false;
|
1498
1505
|
}
|
1499
|
-
|
1506
|
+
shouldUnregister &&
|
1500
1507
|
!(isNameInFieldArray(_names.array, name) && _stateFlags.action) &&
|
1501
1508
|
_names.unMount.add(name);
|
1502
1509
|
}
|
@@ -1513,13 +1520,13 @@ function createFormControl(props = {}) {
|
|
1513
1520
|
isSubmitting: true,
|
1514
1521
|
});
|
1515
1522
|
try {
|
1516
|
-
if (
|
1523
|
+
if (_options.resolver) {
|
1517
1524
|
const { errors, values } = await executeResolver();
|
1518
1525
|
_formState.errors = errors;
|
1519
1526
|
fieldValues = values;
|
1520
1527
|
}
|
1521
1528
|
else {
|
1522
|
-
await
|
1529
|
+
await executeBuildInValidation(_fields);
|
1523
1530
|
}
|
1524
1531
|
if (isEmptyObject(_formState.errors) &&
|
1525
1532
|
Object.keys(_formState.errors).every((name) => get(fieldValues, name))) {
|
@@ -1531,7 +1538,7 @@ function createFormControl(props = {}) {
|
|
1531
1538
|
}
|
1532
1539
|
else {
|
1533
1540
|
onInvalid && (await onInvalid(_formState.errors, e));
|
1534
|
-
|
1541
|
+
_options.shouldFocusError &&
|
1535
1542
|
focusFieldBy(_fields, (key) => get(_formState.errors, key), _names.mount);
|
1536
1543
|
}
|
1537
1544
|
}
|
@@ -1552,22 +1559,23 @@ function createFormControl(props = {}) {
|
|
1552
1559
|
};
|
1553
1560
|
const reset = (formValues, keepStateOptions = {}) => {
|
1554
1561
|
const updatedValues = formValues || _defaultValues;
|
1555
|
-
const
|
1562
|
+
const cloneUpdatedValues = cloneObject(updatedValues);
|
1556
1563
|
if (!keepStateOptions.keepValues) {
|
1557
|
-
_formValues = props.shouldUnregister ? {} :
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1564
|
+
_formValues = props.shouldUnregister ? {} : cloneUpdatedValues;
|
1565
|
+
if (isWeb) {
|
1566
|
+
for (const name of _names.mount) {
|
1567
|
+
const field = get(_fields, name);
|
1568
|
+
if (field && field._f) {
|
1569
|
+
const fieldReference = Array.isArray(field._f.refs)
|
1570
|
+
? field._f.refs[0]
|
1571
|
+
: field._f.ref;
|
1572
|
+
try {
|
1573
|
+
isHTMLElement(fieldReference) &&
|
1574
|
+
fieldReference.closest('form').reset();
|
1575
|
+
break;
|
1576
|
+
}
|
1577
|
+
catch (_a) { }
|
1569
1578
|
}
|
1570
|
-
catch (_a) { }
|
1571
1579
|
}
|
1572
1580
|
}
|
1573
1581
|
}
|
@@ -1583,7 +1591,7 @@ function createFormControl(props = {}) {
|
|
1583
1591
|
});
|
1584
1592
|
_subjects.watch.next({});
|
1585
1593
|
_subjects.array.next({
|
1586
|
-
values,
|
1594
|
+
values: cloneUpdatedValues,
|
1587
1595
|
});
|
1588
1596
|
}
|
1589
1597
|
_names = {
|
@@ -1623,27 +1631,17 @@ function createFormControl(props = {}) {
|
|
1623
1631
|
_stateFlags.watch = !!props.shouldUnregister;
|
1624
1632
|
};
|
1625
1633
|
const setFocus = (name) => get(_fields, name)._f.ref.focus();
|
1626
|
-
const _removeFields = () => {
|
1627
|
-
for (const name of _names.unMount) {
|
1628
|
-
const field = get(_fields, name);
|
1629
|
-
field &&
|
1630
|
-
(field._f.refs ? field._f.refs.every(live) : live(field._f.ref)) &&
|
1631
|
-
unregister(name);
|
1632
|
-
}
|
1633
|
-
_names.unMount = new Set();
|
1634
|
-
};
|
1635
1634
|
return {
|
1636
1635
|
control: {
|
1637
1636
|
register,
|
1638
1637
|
unregister,
|
1639
1638
|
_getWatch,
|
1640
|
-
|
1639
|
+
_getDirty,
|
1641
1640
|
_updateValid,
|
1642
|
-
|
1641
|
+
_removeUnmounted,
|
1643
1642
|
_updateFieldArray,
|
1644
|
-
|
1643
|
+
_getFieldArray,
|
1645
1644
|
_subjects,
|
1646
|
-
_shouldUnregister: formOptions.shouldUnregister,
|
1647
1645
|
_proxyFormState,
|
1648
1646
|
get _fields() {
|
1649
1647
|
return _fields;
|
@@ -1681,8 +1679,11 @@ function createFormControl(props = {}) {
|
|
1681
1679
|
set _formState(value) {
|
1682
1680
|
_formState = value;
|
1683
1681
|
},
|
1684
|
-
|
1685
|
-
|
1682
|
+
get _options() {
|
1683
|
+
return _options;
|
1684
|
+
},
|
1685
|
+
set _options(value) {
|
1686
|
+
_options = Object.assign(Object.assign({}, _options), value);
|
1686
1687
|
},
|
1687
1688
|
},
|
1688
1689
|
trigger,
|
@@ -1714,25 +1715,21 @@ function useForm(props = {}) {
|
|
1714
1715
|
errors: {},
|
1715
1716
|
});
|
1716
1717
|
if (_formControl.current) {
|
1717
|
-
_formControl.current.control.
|
1718
|
+
_formControl.current.control._options = props;
|
1718
1719
|
}
|
1719
1720
|
else {
|
1720
1721
|
_formControl.current = Object.assign(Object.assign({}, createFormControl(props)), { formState });
|
1721
1722
|
}
|
1722
1723
|
const control = _formControl.current.control;
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
return () => {
|
1733
|
-
formStateSubscription.unsubscribe();
|
1734
|
-
};
|
1735
|
-
}, [control]);
|
1724
|
+
useSubscribe({
|
1725
|
+
subject: control._subjects.state,
|
1726
|
+
callback: (formState) => {
|
1727
|
+
if (shouldRenderFormState(formState, control._proxyFormState, true)) {
|
1728
|
+
control._formState = Object.assign(Object.assign({}, control._formState), formState);
|
1729
|
+
updateFormState(Object.assign({}, control._formState));
|
1730
|
+
}
|
1731
|
+
},
|
1732
|
+
});
|
1736
1733
|
React.useEffect(() => {
|
1737
1734
|
if (!control._stateFlags.mount) {
|
1738
1735
|
control._proxyFormState.isValid && control._updateValid();
|
@@ -1742,7 +1739,7 @@ function useForm(props = {}) {
|
|
1742
1739
|
control._stateFlags.watch = false;
|
1743
1740
|
control._subjects.state.next({});
|
1744
1741
|
}
|
1745
|
-
control.
|
1742
|
+
control._removeUnmounted();
|
1746
1743
|
});
|
1747
1744
|
_formControl.current.formState = getProxyFormState(formState, control._proxyFormState);
|
1748
1745
|
return _formControl.current;
|
@@ -1753,31 +1750,30 @@ function useWatch(props) {
|
|
1753
1750
|
const { control = methods.control, name, defaultValue, disabled, } = props || {};
|
1754
1751
|
const _name = React.useRef(name);
|
1755
1752
|
_name.current = name;
|
1753
|
+
useSubscribe({
|
1754
|
+
disabled,
|
1755
|
+
subject: control._subjects.watch,
|
1756
|
+
callback: ({ name }) => {
|
1757
|
+
if (!_name.current ||
|
1758
|
+
!name ||
|
1759
|
+
convertToArrayPayload(_name.current).some((currentName) => name &&
|
1760
|
+
currentName &&
|
1761
|
+
(name.startsWith(currentName) ||
|
1762
|
+
currentName.startsWith(name)))) {
|
1763
|
+
control._stateFlags.mount = true;
|
1764
|
+
const fieldValues = control._getWatch(_name.current, defaultValue);
|
1765
|
+
updateValue(isObject(fieldValues)
|
1766
|
+
? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
|
1767
|
+
? [...fieldValues]
|
1768
|
+
: fieldValues);
|
1769
|
+
}
|
1770
|
+
},
|
1771
|
+
});
|
1756
1772
|
const [value, updateValue] = React.useState(isUndefined(defaultValue)
|
1757
1773
|
? control._getWatch(name)
|
1758
1774
|
: defaultValue);
|
1759
1775
|
React.useEffect(() => {
|
1760
|
-
|
1761
|
-
next: ({ name }) => {
|
1762
|
-
if (!_name.current ||
|
1763
|
-
!name ||
|
1764
|
-
convertToArrayPayload(_name.current).some((fieldName) => name &&
|
1765
|
-
fieldName &&
|
1766
|
-
(fieldName.startsWith(name) ||
|
1767
|
-
name.startsWith(fieldName)))) {
|
1768
|
-
const result = control._getWatch(_name.current, defaultValue, true);
|
1769
|
-
updateValue(isObject(result)
|
1770
|
-
? Object.assign({}, result) : Array.isArray(result)
|
1771
|
-
? [...result]
|
1772
|
-
: result);
|
1773
|
-
}
|
1774
|
-
},
|
1775
|
-
});
|
1776
|
-
disabled && watchSubscription.unsubscribe();
|
1777
|
-
return () => watchSubscription.unsubscribe();
|
1778
|
-
}, [disabled, control, defaultValue]);
|
1779
|
-
React.useEffect(() => {
|
1780
|
-
control._removeFields();
|
1776
|
+
control._removeUnmounted();
|
1781
1777
|
});
|
1782
1778
|
return value;
|
1783
1779
|
}
|