@octanejs/hook-form 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +62 -0
- package/package.json +46 -0
- package/src/FormProvider.tsrx +76 -0
- package/src/FormProvider.tsrx.d.ts +10 -0
- package/src/constants.ts +31 -0
- package/src/controller.tsrx +8 -0
- package/src/controller.tsrx.d.ts +52 -0
- package/src/form.tsrx +119 -0
- package/src/form.tsrx.d.ts +6 -0
- package/src/formStateSubscribe.tsrx +10 -0
- package/src/formStateSubscribe.tsrx.d.ts +16 -0
- package/src/index.ts +19 -0
- package/src/logic/appendErrors.ts +19 -0
- package/src/logic/createFormControl.ts +1841 -0
- package/src/logic/generateId.ts +14 -0
- package/src/logic/generateWatchOutput.ts +27 -0
- package/src/logic/getCheckboxValue.ts +36 -0
- package/src/logic/getDirtyFields.ts +120 -0
- package/src/logic/getEventValue.ts +12 -0
- package/src/logic/getFieldValue.ts +33 -0
- package/src/logic/getFieldValueAs.ts +22 -0
- package/src/logic/getFocusFieldName.ts +13 -0
- package/src/logic/getNodeParentName.ts +4 -0
- package/src/logic/getProxyFormState.ts +33 -0
- package/src/logic/getRadioValue.ts +24 -0
- package/src/logic/getResolverOptions.ts +33 -0
- package/src/logic/getRuleValue.ts +16 -0
- package/src/logic/getValidateError.ts +22 -0
- package/src/logic/getValidationModes.ts +11 -0
- package/src/logic/getValueAndMessage.ts +12 -0
- package/src/logic/hasPromiseValidation.ts +27 -0
- package/src/logic/hasValidation.ts +12 -0
- package/src/logic/index.ts +3 -0
- package/src/logic/isNameInFieldArray.ts +7 -0
- package/src/logic/isWatched.ts +11 -0
- package/src/logic/iterateFieldsByAction.ts +37 -0
- package/src/logic/schemaErrorLookup.ts +54 -0
- package/src/logic/shouldRenderFormState.ts +25 -0
- package/src/logic/shouldSubscribeByName.ts +18 -0
- package/src/logic/skipValidation.ts +21 -0
- package/src/logic/unsetEmptyArray.ts +6 -0
- package/src/logic/updateFieldArrayRootError.ts +17 -0
- package/src/logic/validateField.ts +273 -0
- package/src/types/controller.ts +98 -0
- package/src/types/errors.ts +56 -0
- package/src/types/events.ts +26 -0
- package/src/types/fieldArray.ts +288 -0
- package/src/types/fields.ts +46 -0
- package/src/types/form.ts +961 -0
- package/src/types/index.ts +12 -0
- package/src/types/path/common.ts +391 -0
- package/src/types/path/eager.ts +224 -0
- package/src/types/path/index.ts +16 -0
- package/src/types/resolvers.ts +38 -0
- package/src/types/utils.ts +125 -0
- package/src/types/validator.ts +94 -0
- package/src/types/watch.ts +66 -0
- package/src/useController.ts +268 -0
- package/src/useFieldArray.ts +490 -0
- package/src/useForm.ts +182 -0
- package/src/useFormContext.ts +47 -0
- package/src/useFormControlContext.ts +25 -0
- package/src/useFormState.ts +86 -0
- package/src/useIsomorphicLayoutEffect.ts +6 -0
- package/src/useWatch.ts +356 -0
- package/src/utils/append.ts +4 -0
- package/src/utils/cloneObject.ts +32 -0
- package/src/utils/compact.ts +2 -0
- package/src/utils/convertToArrayPayload.ts +2 -0
- package/src/utils/createSubject.ts +48 -0
- package/src/utils/deepEqual.ts +81 -0
- package/src/utils/deepMerge.ts +27 -0
- package/src/utils/extractFormValues.ts +28 -0
- package/src/utils/fillEmptyArray.ts +3 -0
- package/src/utils/flatten.ts +23 -0
- package/src/utils/get.ts +29 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/insert.ts +8 -0
- package/src/utils/isBoolean.ts +2 -0
- package/src/utils/isCheckBoxInput.ts +4 -0
- package/src/utils/isDateObject.ts +2 -0
- package/src/utils/isEmptyObject.ts +7 -0
- package/src/utils/isFileInput.ts +4 -0
- package/src/utils/isFunction.ts +2 -0
- package/src/utils/isHTMLElement.ts +13 -0
- package/src/utils/isKey.ts +4 -0
- package/src/utils/isMultipleSelect.ts +5 -0
- package/src/utils/isNullOrUndefined.ts +2 -0
- package/src/utils/isObject.ts +8 -0
- package/src/utils/isPlainObject.ts +8 -0
- package/src/utils/isPrimitive.ts +8 -0
- package/src/utils/isRadioInput.ts +4 -0
- package/src/utils/isRadioOrCheckbox.ts +8 -0
- package/src/utils/isRegex.ts +2 -0
- package/src/utils/isString.ts +2 -0
- package/src/utils/isUndefined.ts +2 -0
- package/src/utils/isWeb.ts +4 -0
- package/src/utils/live.ts +6 -0
- package/src/utils/move.ts +15 -0
- package/src/utils/noop.ts +2 -0
- package/src/utils/objectHasFunction.ts +11 -0
- package/src/utils/prepend.ts +7 -0
- package/src/utils/remove.ts +24 -0
- package/src/utils/set.ts +36 -0
- package/src/utils/sleep.ts +2 -0
- package/src/utils/stringToPath.ts +4 -0
- package/src/utils/swap.ts +4 -0
- package/src/utils/unset.ts +65 -0
- package/src/utils/update.ts +5 -0
- package/src/watch.tsrx +7 -0
- package/src/watch.tsrx.d.ts +42 -0
|
@@ -0,0 +1,1841 @@
|
|
|
1
|
+
// Vendored from react-hook-form@7.81.0 src/logic/createFormControl.ts (octane port).
|
|
2
|
+
import { EVENTS, INPUT_VALIDATION_RULES, ROOT_ERROR_TYPE, VALIDATION_MODE } from '../constants';
|
|
3
|
+
import type {
|
|
4
|
+
BatchFieldArrayUpdate,
|
|
5
|
+
ChangeHandler,
|
|
6
|
+
Control,
|
|
7
|
+
DeepPartial,
|
|
8
|
+
DelayCallback,
|
|
9
|
+
EventType,
|
|
10
|
+
Field,
|
|
11
|
+
FieldError,
|
|
12
|
+
FieldErrors,
|
|
13
|
+
FieldNamesMarkedBoolean,
|
|
14
|
+
FieldPath,
|
|
15
|
+
FieldPathValue,
|
|
16
|
+
FieldRefs,
|
|
17
|
+
FieldValues,
|
|
18
|
+
FormState,
|
|
19
|
+
FromSubscribe,
|
|
20
|
+
GetIsDirty,
|
|
21
|
+
GetValuesConfig,
|
|
22
|
+
InternalFieldName,
|
|
23
|
+
Names,
|
|
24
|
+
Path,
|
|
25
|
+
ReadFormState,
|
|
26
|
+
Ref,
|
|
27
|
+
SetFieldValue,
|
|
28
|
+
SetValueConfig,
|
|
29
|
+
Subjects,
|
|
30
|
+
UseFormClearErrors,
|
|
31
|
+
UseFormGetFieldState,
|
|
32
|
+
UseFormGetValues,
|
|
33
|
+
UseFormHandleSubmit,
|
|
34
|
+
UseFormProps,
|
|
35
|
+
UseFormRegister,
|
|
36
|
+
UseFormReset,
|
|
37
|
+
UseFormResetDefaultValues,
|
|
38
|
+
UseFormResetField,
|
|
39
|
+
UseFormReturn,
|
|
40
|
+
UseFormSetError,
|
|
41
|
+
UseFormSetFocus,
|
|
42
|
+
UseFormSetValue,
|
|
43
|
+
UseFormSetValues,
|
|
44
|
+
UseFormSubscribe,
|
|
45
|
+
UseFormTrigger,
|
|
46
|
+
UseFormUnregister,
|
|
47
|
+
UseFormWatch,
|
|
48
|
+
ValidateFormEventType,
|
|
49
|
+
WatchInternal,
|
|
50
|
+
WatchObserver,
|
|
51
|
+
} from '../types';
|
|
52
|
+
import cloneObject from '../utils/cloneObject';
|
|
53
|
+
import compact from '../utils/compact';
|
|
54
|
+
import convertToArrayPayload from '../utils/convertToArrayPayload';
|
|
55
|
+
import createSubject from '../utils/createSubject';
|
|
56
|
+
import deepEqual from '../utils/deepEqual';
|
|
57
|
+
import extractFormValues from '../utils/extractFormValues';
|
|
58
|
+
import { flatten } from '../utils/flatten';
|
|
59
|
+
import get from '../utils/get';
|
|
60
|
+
import isBoolean from '../utils/isBoolean';
|
|
61
|
+
import isCheckBoxInput from '../utils/isCheckBoxInput';
|
|
62
|
+
import isDateObject from '../utils/isDateObject';
|
|
63
|
+
import isEmptyObject from '../utils/isEmptyObject';
|
|
64
|
+
import isFileInput from '../utils/isFileInput';
|
|
65
|
+
import isFunction from '../utils/isFunction';
|
|
66
|
+
import isHTMLElement from '../utils/isHTMLElement';
|
|
67
|
+
import isKey from '../utils/isKey';
|
|
68
|
+
import isMultipleSelect from '../utils/isMultipleSelect';
|
|
69
|
+
import isNullOrUndefined from '../utils/isNullOrUndefined';
|
|
70
|
+
import isObject from '../utils/isObject';
|
|
71
|
+
import isRadioOrCheckbox from '../utils/isRadioOrCheckbox';
|
|
72
|
+
import isString from '../utils/isString';
|
|
73
|
+
import isUndefined from '../utils/isUndefined';
|
|
74
|
+
import isWeb from '../utils/isWeb';
|
|
75
|
+
import live from '../utils/live';
|
|
76
|
+
import set from '../utils/set';
|
|
77
|
+
import stringToPath from '../utils/stringToPath';
|
|
78
|
+
import unset from '../utils/unset';
|
|
79
|
+
|
|
80
|
+
import generateWatchOutput from './generateWatchOutput';
|
|
81
|
+
import getDirtyFields from './getDirtyFields';
|
|
82
|
+
import getEventValue from './getEventValue';
|
|
83
|
+
import getFieldValue from './getFieldValue';
|
|
84
|
+
import getFieldValueAs from './getFieldValueAs';
|
|
85
|
+
import getResolverOptions from './getResolverOptions';
|
|
86
|
+
import getRuleValue from './getRuleValue';
|
|
87
|
+
import getValidationModes from './getValidationModes';
|
|
88
|
+
import hasPromiseValidation from './hasPromiseValidation';
|
|
89
|
+
import hasValidation from './hasValidation';
|
|
90
|
+
import isNameInFieldArray from './isNameInFieldArray';
|
|
91
|
+
import isWatched from './isWatched';
|
|
92
|
+
import iterateFieldsByAction from './iterateFieldsByAction';
|
|
93
|
+
import schemaErrorLookup from './schemaErrorLookup';
|
|
94
|
+
import shouldRenderFormState from './shouldRenderFormState';
|
|
95
|
+
import shouldSubscribeByName from './shouldSubscribeByName';
|
|
96
|
+
import skipValidation from './skipValidation';
|
|
97
|
+
import unsetEmptyArray from './unsetEmptyArray';
|
|
98
|
+
import updateFieldArrayRootError from './updateFieldArrayRootError';
|
|
99
|
+
import validateField from './validateField';
|
|
100
|
+
|
|
101
|
+
const defaultOptions = {
|
|
102
|
+
mode: VALIDATION_MODE.onSubmit,
|
|
103
|
+
reValidateMode: VALIDATION_MODE.onChange,
|
|
104
|
+
shouldFocusError: true,
|
|
105
|
+
} as const;
|
|
106
|
+
|
|
107
|
+
const FORM_ERROR_TYPE = 'form';
|
|
108
|
+
|
|
109
|
+
export const DEFAULT_FORM_STATE = {
|
|
110
|
+
submitCount: 0,
|
|
111
|
+
isDirty: false,
|
|
112
|
+
isReady: false,
|
|
113
|
+
isValidating: false,
|
|
114
|
+
isSubmitted: false,
|
|
115
|
+
isSubmitting: false,
|
|
116
|
+
isSubmitSuccessful: false,
|
|
117
|
+
isValid: false,
|
|
118
|
+
touchedFields: {},
|
|
119
|
+
dirtyFields: {},
|
|
120
|
+
validatingFields: {},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export function createFormControl<
|
|
124
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
125
|
+
TContext = any,
|
|
126
|
+
TTransformedValues = TFieldValues,
|
|
127
|
+
>(
|
|
128
|
+
props: UseFormProps<TFieldValues, TContext, TTransformedValues> = {},
|
|
129
|
+
): Omit<UseFormReturn<TFieldValues, TContext, TTransformedValues>, 'formState'> & {
|
|
130
|
+
formControl: Omit<UseFormReturn<TFieldValues, TContext, TTransformedValues>, 'formState'>;
|
|
131
|
+
} {
|
|
132
|
+
let _options = {
|
|
133
|
+
...defaultOptions,
|
|
134
|
+
...props,
|
|
135
|
+
};
|
|
136
|
+
let _formState: FormState<TFieldValues> & {
|
|
137
|
+
values?: TFieldValues;
|
|
138
|
+
name?: string;
|
|
139
|
+
type?: EventType;
|
|
140
|
+
} = {
|
|
141
|
+
...cloneObject(DEFAULT_FORM_STATE),
|
|
142
|
+
isLoading: isFunction(_options.defaultValues),
|
|
143
|
+
errors: _options.errors || {},
|
|
144
|
+
disabled: _options.disabled || false,
|
|
145
|
+
};
|
|
146
|
+
let _fields: FieldRefs = {};
|
|
147
|
+
let _defaultValues =
|
|
148
|
+
isObject(_options.defaultValues) || isObject(_options.values)
|
|
149
|
+
? cloneObject(_options.defaultValues || _options.values) || {}
|
|
150
|
+
: {};
|
|
151
|
+
let _formValues = _options.shouldUnregister
|
|
152
|
+
? ({} as TFieldValues)
|
|
153
|
+
: (cloneObject(_defaultValues) as TFieldValues);
|
|
154
|
+
let _state = {
|
|
155
|
+
action: false,
|
|
156
|
+
mount: false,
|
|
157
|
+
watch: false,
|
|
158
|
+
keepIsValid: false,
|
|
159
|
+
};
|
|
160
|
+
let _names: Names = {
|
|
161
|
+
mount: new Set(),
|
|
162
|
+
disabled: new Set(),
|
|
163
|
+
unMount: new Set(),
|
|
164
|
+
array: new Set(),
|
|
165
|
+
watch: new Set(),
|
|
166
|
+
registerName: new Set(),
|
|
167
|
+
};
|
|
168
|
+
let delayErrorCallback: DelayCallback | null;
|
|
169
|
+
let timer = 0;
|
|
170
|
+
let _valuesSubscriberCount = 0;
|
|
171
|
+
let _validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
172
|
+
let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
173
|
+
const defaultProxyFormState: ReadFormState = {
|
|
174
|
+
isDirty: false,
|
|
175
|
+
dirtyFields: false,
|
|
176
|
+
validatingFields: false,
|
|
177
|
+
touchedFields: false,
|
|
178
|
+
isValidating: false,
|
|
179
|
+
isValid: false,
|
|
180
|
+
errors: false,
|
|
181
|
+
};
|
|
182
|
+
const _proxyFormState: ReadFormState = {
|
|
183
|
+
...defaultProxyFormState,
|
|
184
|
+
};
|
|
185
|
+
let _proxySubscribeFormState = {
|
|
186
|
+
..._proxyFormState,
|
|
187
|
+
};
|
|
188
|
+
const _subjects: Subjects<TFieldValues> = {
|
|
189
|
+
array: createSubject(),
|
|
190
|
+
state: createSubject(),
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
|
194
|
+
|
|
195
|
+
const debounce =
|
|
196
|
+
<T extends Function>(callback: T) =>
|
|
197
|
+
(wait: number) => {
|
|
198
|
+
clearTimeout(timer);
|
|
199
|
+
timer = setTimeout(callback, wait);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const _setValid = async (shouldUpdateValid?: boolean) => {
|
|
203
|
+
if (_state.keepIsValid) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (
|
|
207
|
+
!_options.disabled &&
|
|
208
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid || shouldUpdateValid)
|
|
209
|
+
) {
|
|
210
|
+
let isValid: boolean;
|
|
211
|
+
if (_options.resolver) {
|
|
212
|
+
isValid = isEmptyObject((await _runSchema()).errors);
|
|
213
|
+
_updateIsValidating();
|
|
214
|
+
} else {
|
|
215
|
+
isValid = await executeBuiltInValidation({
|
|
216
|
+
fields: _fields,
|
|
217
|
+
onlyCheckValid: true,
|
|
218
|
+
eventType: EVENTS.VALID,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (isValid !== _formState.isValid) {
|
|
222
|
+
_subjects.state.next({
|
|
223
|
+
isValid,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const _updateIsValidating = (names?: string[], isValidating?: boolean) => {
|
|
230
|
+
if (
|
|
231
|
+
!_options.disabled &&
|
|
232
|
+
(_proxyFormState.isValidating ||
|
|
233
|
+
_proxyFormState.validatingFields ||
|
|
234
|
+
_proxySubscribeFormState.isValidating ||
|
|
235
|
+
_proxySubscribeFormState.validatingFields)
|
|
236
|
+
) {
|
|
237
|
+
(names || Array.from(_names.mount)).forEach((name) => {
|
|
238
|
+
if (name) {
|
|
239
|
+
isValidating
|
|
240
|
+
? set(_formState.validatingFields, name, isValidating)
|
|
241
|
+
: unset(_formState.validatingFields, name);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
_subjects.state.next({
|
|
246
|
+
validatingFields: _formState.validatingFields,
|
|
247
|
+
isValidating: !isEmptyObject(_formState.validatingFields),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const _updateDirtyFields = () => {
|
|
253
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const _setFieldArray: BatchFieldArrayUpdate = (
|
|
257
|
+
name,
|
|
258
|
+
values = [],
|
|
259
|
+
method,
|
|
260
|
+
args,
|
|
261
|
+
shouldSetValues = true,
|
|
262
|
+
shouldUpdateFieldsAndState = true,
|
|
263
|
+
) => {
|
|
264
|
+
if (args && method && !_options.disabled) {
|
|
265
|
+
_state.action = true;
|
|
266
|
+
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
|
|
267
|
+
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
|
268
|
+
shouldSetValues && set(_fields, name, fieldValues);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (shouldUpdateFieldsAndState && Array.isArray(get(_formState.errors, name))) {
|
|
272
|
+
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
|
273
|
+
shouldSetValues && set(_formState.errors, name, errors);
|
|
274
|
+
unsetEmptyArray(_formState.errors, name);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (
|
|
278
|
+
(_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) &&
|
|
279
|
+
shouldUpdateFieldsAndState &&
|
|
280
|
+
Array.isArray(get(_formState.touchedFields, name))
|
|
281
|
+
) {
|
|
282
|
+
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
|
283
|
+
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
|
287
|
+
_updateDirtyFields();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
_subjects.state.next({
|
|
291
|
+
name,
|
|
292
|
+
isDirty: _getDirty(name, values),
|
|
293
|
+
dirtyFields: _formState.dirtyFields,
|
|
294
|
+
errors: _formState.errors,
|
|
295
|
+
isValid: _formState.isValid,
|
|
296
|
+
});
|
|
297
|
+
} else {
|
|
298
|
+
set(_formValues, name, values);
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const updateErrors = (name: InternalFieldName, error: FieldError) => {
|
|
303
|
+
set(_formState.errors, name, error);
|
|
304
|
+
_formState.errors = { ..._formState.errors };
|
|
305
|
+
_subjects.state.next({
|
|
306
|
+
errors: _formState.errors,
|
|
307
|
+
});
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const _setErrors = (errors: FieldErrors<TFieldValues>) => {
|
|
311
|
+
_formState.errors = errors;
|
|
312
|
+
_subjects.state.next({
|
|
313
|
+
errors: _formState.errors,
|
|
314
|
+
isValid: false,
|
|
315
|
+
});
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const hasExplicitNullIntermediate = (name: InternalFieldName) => {
|
|
319
|
+
const segments = isKey(name) ? [name] : stringToPath(name);
|
|
320
|
+
let formValues = _formValues;
|
|
321
|
+
let defaultValues = _defaultValues;
|
|
322
|
+
|
|
323
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
324
|
+
const key = segments[i];
|
|
325
|
+
|
|
326
|
+
formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
|
|
327
|
+
|
|
328
|
+
defaultValues = isNullOrUndefined(defaultValues)
|
|
329
|
+
? defaultValues
|
|
330
|
+
: defaultValues[key as keyof typeof defaultValues];
|
|
331
|
+
|
|
332
|
+
if (formValues === null && defaultValues !== null) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return false;
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const updateValidAndValue = (
|
|
341
|
+
name: InternalFieldName,
|
|
342
|
+
shouldSkipSetValueAs: boolean,
|
|
343
|
+
value?: unknown,
|
|
344
|
+
ref?: Ref,
|
|
345
|
+
) => {
|
|
346
|
+
const field: Field = get(_fields, name);
|
|
347
|
+
|
|
348
|
+
if (field) {
|
|
349
|
+
if (hasExplicitNullIntermediate(name)) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const wasUnsetInFormValues = isUndefined(get(_formValues, name));
|
|
354
|
+
const defaultValue = get(
|
|
355
|
+
_formValues,
|
|
356
|
+
name,
|
|
357
|
+
isUndefined(value) ? get(_defaultValues, name) : value,
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
isUndefined(defaultValue) ||
|
|
361
|
+
(ref && (ref as HTMLInputElement).defaultChecked) ||
|
|
362
|
+
shouldSkipSetValueAs
|
|
363
|
+
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
|
364
|
+
: setFieldValue(name, defaultValue);
|
|
365
|
+
|
|
366
|
+
if (_state.mount && !_state.action) {
|
|
367
|
+
_setValid();
|
|
368
|
+
|
|
369
|
+
if (
|
|
370
|
+
wasUnsetInFormValues &&
|
|
371
|
+
_formState.isDirty &&
|
|
372
|
+
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)
|
|
373
|
+
) {
|
|
374
|
+
const isDirty = _getDirty();
|
|
375
|
+
if (!isDirty) {
|
|
376
|
+
_formState.isDirty = false;
|
|
377
|
+
_subjects.state.next({ ..._formState });
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (
|
|
382
|
+
props.shouldUnregister &&
|
|
383
|
+
wasUnsetInFormValues &&
|
|
384
|
+
!isUndefined(get(_formValues, name)) &&
|
|
385
|
+
isWatched(name, _names)
|
|
386
|
+
) {
|
|
387
|
+
_state.watch = true;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
const updateTouchAndDirty = (
|
|
394
|
+
name: InternalFieldName,
|
|
395
|
+
fieldValue: unknown,
|
|
396
|
+
isBlurEvent?: boolean,
|
|
397
|
+
shouldDirty?: boolean,
|
|
398
|
+
shouldRender?: boolean,
|
|
399
|
+
): Partial<Pick<FormState<TFieldValues>, 'dirtyFields' | 'isDirty' | 'touchedFields'>> => {
|
|
400
|
+
let shouldUpdateField = false;
|
|
401
|
+
let isPreviousDirty = false;
|
|
402
|
+
const output: Partial<FormState<TFieldValues>> & { name: string } = {
|
|
403
|
+
name,
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
if (!_options.disabled) {
|
|
407
|
+
if (!isBlurEvent || shouldDirty) {
|
|
408
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
409
|
+
|
|
410
|
+
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
411
|
+
isPreviousDirty = _formState.isDirty;
|
|
412
|
+
|
|
413
|
+
_formState.isDirty = output.isDirty = !isCurrentFieldPristine || _getDirty();
|
|
414
|
+
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
418
|
+
|
|
419
|
+
if (isCurrentFieldPristine !== _formState.isDirty) {
|
|
420
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
421
|
+
} else {
|
|
422
|
+
isCurrentFieldPristine
|
|
423
|
+
? unset(_formState.dirtyFields, name)
|
|
424
|
+
: set(_formState.dirtyFields, name, true);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
output.dirtyFields = _formState.dirtyFields;
|
|
428
|
+
shouldUpdateField =
|
|
429
|
+
shouldUpdateField ||
|
|
430
|
+
((_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) &&
|
|
431
|
+
isPreviousDirty !== !isCurrentFieldPristine);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (isBlurEvent) {
|
|
435
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
|
436
|
+
|
|
437
|
+
if (!isPreviousFieldTouched) {
|
|
438
|
+
set(_formState.touchedFields, name, isBlurEvent);
|
|
439
|
+
output.touchedFields = _formState.touchedFields;
|
|
440
|
+
shouldUpdateField =
|
|
441
|
+
shouldUpdateField ||
|
|
442
|
+
((_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) &&
|
|
443
|
+
isPreviousFieldTouched !== isBlurEvent);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return shouldUpdateField ? output : {};
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
const shouldRenderByError = (
|
|
454
|
+
name: InternalFieldName,
|
|
455
|
+
isValid?: boolean,
|
|
456
|
+
error?: FieldError,
|
|
457
|
+
fieldState?: {
|
|
458
|
+
dirty?: FieldNamesMarkedBoolean<TFieldValues>;
|
|
459
|
+
isDirty?: boolean;
|
|
460
|
+
touched?: FieldNamesMarkedBoolean<TFieldValues>;
|
|
461
|
+
},
|
|
462
|
+
) => {
|
|
463
|
+
const previousFieldError = get(_formState.errors, name);
|
|
464
|
+
const shouldUpdateValid =
|
|
465
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
466
|
+
isBoolean(isValid) &&
|
|
467
|
+
_formState.isValid !== isValid;
|
|
468
|
+
|
|
469
|
+
if (_options.delayError && error) {
|
|
470
|
+
delayErrorCallback = debounce(() => updateErrors(name, error));
|
|
471
|
+
delayErrorCallback(_options.delayError);
|
|
472
|
+
} else {
|
|
473
|
+
clearTimeout(timer);
|
|
474
|
+
delayErrorCallback = null;
|
|
475
|
+
error ? set(_formState.errors, name, error) : unset(_formState.errors, name);
|
|
476
|
+
_formState.errors = { ..._formState.errors };
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (
|
|
480
|
+
(error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
|
481
|
+
!isEmptyObject(fieldState) ||
|
|
482
|
+
shouldUpdateValid
|
|
483
|
+
) {
|
|
484
|
+
const updatedFormState = {
|
|
485
|
+
...fieldState,
|
|
486
|
+
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
|
487
|
+
errors: _formState.errors,
|
|
488
|
+
name,
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
_formState = {
|
|
492
|
+
..._formState,
|
|
493
|
+
...updatedFormState,
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
_subjects.state.next(updatedFormState);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
const _runSchema = async (name?: InternalFieldName[]) => {
|
|
501
|
+
_updateIsValidating(name, true);
|
|
502
|
+
return await _options.resolver!(
|
|
503
|
+
_formValues as TFieldValues,
|
|
504
|
+
_options.context,
|
|
505
|
+
getResolverOptions(
|
|
506
|
+
name || _names.mount,
|
|
507
|
+
_fields,
|
|
508
|
+
_options.criteriaMode,
|
|
509
|
+
_options.shouldUseNativeValidation,
|
|
510
|
+
),
|
|
511
|
+
);
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
const executeSchemaAndUpdateState = async (names?: InternalFieldName[]) => {
|
|
515
|
+
const { errors } = await _runSchema(names);
|
|
516
|
+
_updateIsValidating(names);
|
|
517
|
+
|
|
518
|
+
if (names) {
|
|
519
|
+
for (const name of names) {
|
|
520
|
+
const error = get(errors, name);
|
|
521
|
+
error
|
|
522
|
+
? _names.array.has(name) &&
|
|
523
|
+
isObject(error) &&
|
|
524
|
+
!Object.keys(error).some((key) => !Number.isNaN(Number(key)))
|
|
525
|
+
? updateFieldArrayRootError(
|
|
526
|
+
_formState.errors,
|
|
527
|
+
{ [name]: error } as Partial<Record<string, FieldError>>,
|
|
528
|
+
name,
|
|
529
|
+
)
|
|
530
|
+
: set(_formState.errors, name, error)
|
|
531
|
+
: unset(_formState.errors, name);
|
|
532
|
+
}
|
|
533
|
+
_formState.errors = { ..._formState.errors };
|
|
534
|
+
} else {
|
|
535
|
+
_formState.errors = errors;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return errors;
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
const validateForm = async ({
|
|
542
|
+
name,
|
|
543
|
+
eventType,
|
|
544
|
+
}: {
|
|
545
|
+
name: FieldPath<TFieldValues> | FieldPath<TFieldValues>[] | undefined;
|
|
546
|
+
eventType: ValidateFormEventType;
|
|
547
|
+
}) => {
|
|
548
|
+
if (props.validate) {
|
|
549
|
+
const result = await props.validate({
|
|
550
|
+
formValues: _formValues,
|
|
551
|
+
formState: _formState,
|
|
552
|
+
name,
|
|
553
|
+
eventType,
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
if (isObject(result)) {
|
|
557
|
+
for (const key in result) {
|
|
558
|
+
const error = result[key];
|
|
559
|
+
|
|
560
|
+
if (error) {
|
|
561
|
+
setError(`${FORM_ERROR_TYPE}.${key}`, {
|
|
562
|
+
message: isString(error.message) ? error.message : '',
|
|
563
|
+
type: error.type || INPUT_VALIDATION_RULES.validate,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
} else if (isString(result) || !result) {
|
|
568
|
+
setError(FORM_ERROR_TYPE, {
|
|
569
|
+
message: result || '',
|
|
570
|
+
type: INPUT_VALIDATION_RULES.validate,
|
|
571
|
+
});
|
|
572
|
+
} else {
|
|
573
|
+
clearErrors(FORM_ERROR_TYPE);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
return result;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return true;
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
const executeBuiltInValidation = async ({
|
|
583
|
+
fields,
|
|
584
|
+
onlyCheckValid,
|
|
585
|
+
name,
|
|
586
|
+
eventType,
|
|
587
|
+
context = {
|
|
588
|
+
valid: true,
|
|
589
|
+
runRootValidation: false,
|
|
590
|
+
},
|
|
591
|
+
}: {
|
|
592
|
+
fields: FieldRefs;
|
|
593
|
+
onlyCheckValid?: boolean;
|
|
594
|
+
name?: FieldPath<TFieldValues> | FieldPath<TFieldValues>[];
|
|
595
|
+
eventType: ValidateFormEventType;
|
|
596
|
+
context?: {
|
|
597
|
+
valid: boolean;
|
|
598
|
+
runRootValidation?: boolean;
|
|
599
|
+
};
|
|
600
|
+
}) => {
|
|
601
|
+
if (props.validate) {
|
|
602
|
+
context.runRootValidation = true;
|
|
603
|
+
const result = await validateForm({
|
|
604
|
+
name,
|
|
605
|
+
eventType,
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
if (!result) {
|
|
609
|
+
context.valid = false;
|
|
610
|
+
|
|
611
|
+
if (onlyCheckValid) {
|
|
612
|
+
return context.valid;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
for (const name in fields) {
|
|
618
|
+
const field = fields[name];
|
|
619
|
+
|
|
620
|
+
if (field) {
|
|
621
|
+
const { _f, ...fieldValue } = field as Field;
|
|
622
|
+
|
|
623
|
+
if (_f) {
|
|
624
|
+
const isFieldArrayRoot = _names.array.has(_f.name);
|
|
625
|
+
const isPromiseFunction = field._f && hasPromiseValidation((field as Field)._f);
|
|
626
|
+
const shouldTrackIsValidatingState =
|
|
627
|
+
_proxyFormState.validatingFields ||
|
|
628
|
+
_proxyFormState.isValidating ||
|
|
629
|
+
_proxySubscribeFormState.validatingFields ||
|
|
630
|
+
_proxySubscribeFormState.isValidating;
|
|
631
|
+
|
|
632
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
633
|
+
_updateIsValidating([_f.name], true);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const fieldError = await validateField(
|
|
637
|
+
field as Field,
|
|
638
|
+
_names.disabled,
|
|
639
|
+
_formValues,
|
|
640
|
+
shouldDisplayAllAssociatedErrors,
|
|
641
|
+
_options.shouldUseNativeValidation && !onlyCheckValid,
|
|
642
|
+
isFieldArrayRoot,
|
|
643
|
+
);
|
|
644
|
+
|
|
645
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
646
|
+
_updateIsValidating([_f.name]);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (fieldError[_f.name]) {
|
|
650
|
+
context.valid = false;
|
|
651
|
+
|
|
652
|
+
if (onlyCheckValid) {
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
!onlyCheckValid &&
|
|
658
|
+
(get(fieldError, _f.name)
|
|
659
|
+
? isFieldArrayRoot
|
|
660
|
+
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
|
661
|
+
: set(_formState.errors, _f.name, fieldError[_f.name])
|
|
662
|
+
: unset(_formState.errors, _f.name));
|
|
663
|
+
|
|
664
|
+
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
!isEmptyObject(fieldValue) &&
|
|
670
|
+
(await executeBuiltInValidation({
|
|
671
|
+
context,
|
|
672
|
+
onlyCheckValid,
|
|
673
|
+
fields: fieldValue,
|
|
674
|
+
name: name as FieldPath<TFieldValues>,
|
|
675
|
+
eventType,
|
|
676
|
+
}));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return context.valid;
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
const _removeUnmounted = () => {
|
|
684
|
+
for (const name of _names.unMount) {
|
|
685
|
+
const field: Field = get(_fields, name);
|
|
686
|
+
|
|
687
|
+
field &&
|
|
688
|
+
(field._f.refs ? field._f.refs.every((ref) => !live(ref)) : !live(field._f.ref)) &&
|
|
689
|
+
unregister(name as FieldPath<TFieldValues>);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
_names.unMount = new Set();
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
const _getDirty: GetIsDirty = (name, data) =>
|
|
696
|
+
!_options.disabled &&
|
|
697
|
+
(name && data && set(_formValues, name, data),
|
|
698
|
+
!deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
|
|
699
|
+
|
|
700
|
+
const _getWatch: WatchInternal<TFieldValues> = (names, defaultValue, isGlobal) =>
|
|
701
|
+
generateWatchOutput(
|
|
702
|
+
names,
|
|
703
|
+
_names,
|
|
704
|
+
{
|
|
705
|
+
...(_state.mount
|
|
706
|
+
? _formValues
|
|
707
|
+
: isUndefined(defaultValue)
|
|
708
|
+
? _defaultValues
|
|
709
|
+
: isString(names)
|
|
710
|
+
? { [names]: defaultValue }
|
|
711
|
+
: defaultValue),
|
|
712
|
+
},
|
|
713
|
+
isGlobal,
|
|
714
|
+
defaultValue,
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
const _getFieldArray = <TFieldArrayValues>(
|
|
718
|
+
name: InternalFieldName,
|
|
719
|
+
): Partial<TFieldArrayValues>[] =>
|
|
720
|
+
compact(
|
|
721
|
+
get(
|
|
722
|
+
_state.mount ? _formValues : _defaultValues,
|
|
723
|
+
name,
|
|
724
|
+
_options.shouldUnregister ? get(_defaultValues, name, []) : [],
|
|
725
|
+
),
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
const setFieldValue = (
|
|
729
|
+
name: InternalFieldName,
|
|
730
|
+
value: SetFieldValue<TFieldValues>,
|
|
731
|
+
options: SetValueConfig = {},
|
|
732
|
+
skipClone = false,
|
|
733
|
+
skipRender = false,
|
|
734
|
+
) => {
|
|
735
|
+
const field: Field = get(_fields, name);
|
|
736
|
+
let fieldValue: unknown = value;
|
|
737
|
+
|
|
738
|
+
if (field) {
|
|
739
|
+
const fieldReference = field._f;
|
|
740
|
+
|
|
741
|
+
if (fieldReference) {
|
|
742
|
+
!fieldReference.disabled && set(_formValues, name, getFieldValueAs(value, fieldReference));
|
|
743
|
+
|
|
744
|
+
fieldValue = isHTMLElement(fieldReference.ref) && isNullOrUndefined(value) ? '' : value;
|
|
745
|
+
|
|
746
|
+
if (isMultipleSelect(fieldReference.ref)) {
|
|
747
|
+
[...fieldReference.ref.options].forEach(
|
|
748
|
+
(optionRef) =>
|
|
749
|
+
(optionRef.selected = (fieldValue as InternalFieldName[]).includes(optionRef.value)),
|
|
750
|
+
);
|
|
751
|
+
} else if (fieldReference.refs) {
|
|
752
|
+
if (isCheckBoxInput(fieldReference.ref)) {
|
|
753
|
+
fieldReference.refs.forEach((checkboxRef) => {
|
|
754
|
+
if (!checkboxRef.defaultChecked || !checkboxRef.disabled) {
|
|
755
|
+
if (Array.isArray(fieldValue)) {
|
|
756
|
+
checkboxRef.checked = !!fieldValue.find(
|
|
757
|
+
(data: string) => data === checkboxRef.value,
|
|
758
|
+
);
|
|
759
|
+
} else {
|
|
760
|
+
checkboxRef.checked = fieldValue === checkboxRef.value || !!fieldValue;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
} else {
|
|
765
|
+
fieldReference.refs.forEach(
|
|
766
|
+
(radioRef: HTMLInputElement) => (radioRef.checked = radioRef.value === fieldValue),
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
} else if (isFileInput(fieldReference.ref)) {
|
|
770
|
+
fieldReference.ref.value = '';
|
|
771
|
+
} else {
|
|
772
|
+
fieldReference.ref.value = fieldValue;
|
|
773
|
+
|
|
774
|
+
if (!fieldReference.ref.type && !skipRender) {
|
|
775
|
+
_subjects.state.next({
|
|
776
|
+
name,
|
|
777
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
(options.shouldDirty || options.shouldTouch) &&
|
|
785
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
|
|
786
|
+
|
|
787
|
+
options.shouldValidate && trigger(name as Path<TFieldValues>);
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
const setFieldValues = <
|
|
791
|
+
T extends InternalFieldName,
|
|
792
|
+
K extends SetFieldValue<TFieldValues>,
|
|
793
|
+
U extends SetValueConfig,
|
|
794
|
+
>(
|
|
795
|
+
name: T,
|
|
796
|
+
value: K,
|
|
797
|
+
options: U,
|
|
798
|
+
skipClone = false,
|
|
799
|
+
skipRender = false,
|
|
800
|
+
) => {
|
|
801
|
+
for (const fieldKey in value) {
|
|
802
|
+
if (!value.hasOwnProperty(fieldKey)) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
const fieldValue = value[fieldKey];
|
|
806
|
+
const fieldName = name + '.' + fieldKey;
|
|
807
|
+
const field = get(_fields, fieldName);
|
|
808
|
+
|
|
809
|
+
(_names.array.has(name) || isObject(fieldValue) || (field && !field._f)) &&
|
|
810
|
+
!isDateObject(fieldValue)
|
|
811
|
+
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
812
|
+
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
const _setValue = <TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(
|
|
817
|
+
name: TFieldName,
|
|
818
|
+
value: FieldPathValue<TFieldValues, TFieldName>,
|
|
819
|
+
options: SetValueConfig,
|
|
820
|
+
skipClone: boolean,
|
|
821
|
+
skipStateEmit = false,
|
|
822
|
+
) => {
|
|
823
|
+
const field = get(_fields, name);
|
|
824
|
+
const isFieldArray = _names.array.has(name);
|
|
825
|
+
const cloneValue = skipClone ? value : cloneObject(value);
|
|
826
|
+
const previousValue = get(_formValues, name);
|
|
827
|
+
const isValueUnchanged = deepEqual(previousValue, cloneValue);
|
|
828
|
+
|
|
829
|
+
if (!isValueUnchanged) {
|
|
830
|
+
set(_formValues, name, cloneValue);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
if (isFieldArray) {
|
|
834
|
+
_subjects.array.next({
|
|
835
|
+
name,
|
|
836
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
if (
|
|
840
|
+
(_proxyFormState.isDirty ||
|
|
841
|
+
_proxyFormState.dirtyFields ||
|
|
842
|
+
_proxySubscribeFormState.isDirty ||
|
|
843
|
+
_proxySubscribeFormState.dirtyFields) &&
|
|
844
|
+
options.shouldDirty
|
|
845
|
+
) {
|
|
846
|
+
_updateDirtyFields();
|
|
847
|
+
|
|
848
|
+
if (!skipStateEmit) {
|
|
849
|
+
_subjects.state.next({
|
|
850
|
+
name,
|
|
851
|
+
dirtyFields: _formState.dirtyFields,
|
|
852
|
+
isDirty: _getDirty(name, cloneValue),
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
} else {
|
|
857
|
+
const isEmpty =
|
|
858
|
+
(Array.isArray(cloneValue) && !cloneValue.length) || isEmptyObject(cloneValue);
|
|
859
|
+
|
|
860
|
+
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
861
|
+
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
862
|
+
} else {
|
|
863
|
+
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if (!isValueUnchanged && !skipStateEmit) {
|
|
868
|
+
const watched = isWatched(name, _names);
|
|
869
|
+
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
870
|
+
|
|
871
|
+
_subjects.state.next({
|
|
872
|
+
...(watched && _formState),
|
|
873
|
+
name: _state.mount || watched ? name : undefined,
|
|
874
|
+
values,
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
const setValue: UseFormSetValue<TFieldValues> = (name, value, options = {}) =>
|
|
880
|
+
_setValue(name, value, options, false);
|
|
881
|
+
|
|
882
|
+
const setValues: UseFormSetValues<TFieldValues> = (formValues, options = {}) => {
|
|
883
|
+
const updatedFormValues = isFunction(formValues)
|
|
884
|
+
? (formValues as Function)(_formValues as TFieldValues)
|
|
885
|
+
: formValues;
|
|
886
|
+
|
|
887
|
+
if (!deepEqual(_formValues, updatedFormValues)) {
|
|
888
|
+
_formValues = {
|
|
889
|
+
..._formValues,
|
|
890
|
+
...updatedFormValues,
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
const flattenedUpdates = flatten(updatedFormValues as FieldValues);
|
|
894
|
+
|
|
895
|
+
for (const fieldName of _names.mount) {
|
|
896
|
+
if (fieldName in flattenedUpdates) {
|
|
897
|
+
_setValue(
|
|
898
|
+
fieldName as FieldPath<TFieldValues>,
|
|
899
|
+
flattenedUpdates[fieldName],
|
|
900
|
+
options,
|
|
901
|
+
true,
|
|
902
|
+
true,
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
_subjects.state.next({
|
|
908
|
+
..._formState,
|
|
909
|
+
name: undefined,
|
|
910
|
+
type: undefined,
|
|
911
|
+
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
if (options.shouldValidate) {
|
|
915
|
+
_setValid();
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
|
|
920
|
+
const onChange: ChangeHandler = async (event) => {
|
|
921
|
+
_state.mount = true;
|
|
922
|
+
const target = event.target;
|
|
923
|
+
let name: string = target.name;
|
|
924
|
+
let isFieldValueUpdated = true;
|
|
925
|
+
const field: Field = get(_fields, name);
|
|
926
|
+
const _updateIsFieldValueUpdated = (fieldValue: unknown) => {
|
|
927
|
+
isFieldValueUpdated =
|
|
928
|
+
Number.isNaN(fieldValue) ||
|
|
929
|
+
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
930
|
+
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
if (field) {
|
|
934
|
+
let error;
|
|
935
|
+
let isValid;
|
|
936
|
+
const fieldValue = target.type ? getFieldValue(field._f) : getEventValue(event);
|
|
937
|
+
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
938
|
+
const hasNoValidationEffect =
|
|
939
|
+
!hasValidation(field._f) &&
|
|
940
|
+
!props.validate &&
|
|
941
|
+
!_options.resolver &&
|
|
942
|
+
!get(_formState.errors, name) &&
|
|
943
|
+
!field._f.deps;
|
|
944
|
+
const shouldSkipValidation =
|
|
945
|
+
hasNoValidationEffect ||
|
|
946
|
+
skipValidation(
|
|
947
|
+
isBlurEvent,
|
|
948
|
+
get(_formState.touchedFields, name),
|
|
949
|
+
_formState.isSubmitted,
|
|
950
|
+
_validationModeAfterSubmit,
|
|
951
|
+
_validationModeBeforeSubmit,
|
|
952
|
+
);
|
|
953
|
+
const watched = isWatched(name, _names, isBlurEvent);
|
|
954
|
+
|
|
955
|
+
set(_formValues, name, fieldValue);
|
|
956
|
+
|
|
957
|
+
if (isBlurEvent) {
|
|
958
|
+
if (!target || !target.readOnly) {
|
|
959
|
+
field._f.onBlur && field._f.onBlur(event);
|
|
960
|
+
delayErrorCallback && delayErrorCallback(0);
|
|
961
|
+
}
|
|
962
|
+
} else if (field._f.onChange) {
|
|
963
|
+
field._f.onChange(event);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
|
|
967
|
+
|
|
968
|
+
const shouldRender = !isEmptyObject(fieldState) || watched;
|
|
969
|
+
|
|
970
|
+
!isBlurEvent &&
|
|
971
|
+
_subjects.state.next({
|
|
972
|
+
name,
|
|
973
|
+
type: event.type,
|
|
974
|
+
...(_valuesSubscriberCount ? { values: cloneObject(_formValues) } : {}),
|
|
975
|
+
});
|
|
976
|
+
|
|
977
|
+
if (shouldSkipValidation) {
|
|
978
|
+
if (
|
|
979
|
+
(!hasNoValidationEffect || !_formState.isValid) &&
|
|
980
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)
|
|
981
|
+
) {
|
|
982
|
+
if (_options.mode === 'onBlur') {
|
|
983
|
+
if (isBlurEvent) {
|
|
984
|
+
_setValid();
|
|
985
|
+
}
|
|
986
|
+
} else if (!isBlurEvent) {
|
|
987
|
+
_setValid();
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
return shouldRender && _subjects.state.next({ name, ...(watched ? {} : fieldState) });
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
if (!_options.resolver && props.validate) {
|
|
995
|
+
await validateForm({
|
|
996
|
+
name: name as FieldPath<TFieldValues>,
|
|
997
|
+
eventType: event.type,
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
|
|
1002
|
+
|
|
1003
|
+
if (_options.resolver) {
|
|
1004
|
+
const { errors } = await _runSchema([name]);
|
|
1005
|
+
_updateIsValidating([name]);
|
|
1006
|
+
|
|
1007
|
+
_updateIsFieldValueUpdated(fieldValue);
|
|
1008
|
+
|
|
1009
|
+
if (!isFieldValueUpdated) {
|
|
1010
|
+
!isEmptyObject(fieldState) && _subjects.state.next(fieldState);
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
|
1015
|
+
const errorLookupResult = schemaErrorLookup(
|
|
1016
|
+
errors,
|
|
1017
|
+
_fields,
|
|
1018
|
+
previousErrorLookupResult.name || name,
|
|
1019
|
+
);
|
|
1020
|
+
|
|
1021
|
+
error = errorLookupResult.error;
|
|
1022
|
+
name = errorLookupResult.name;
|
|
1023
|
+
|
|
1024
|
+
isValid = isEmptyObject(errors);
|
|
1025
|
+
} else {
|
|
1026
|
+
_updateIsValidating([name], true);
|
|
1027
|
+
error = (
|
|
1028
|
+
await validateField(
|
|
1029
|
+
field,
|
|
1030
|
+
_names.disabled,
|
|
1031
|
+
_formValues,
|
|
1032
|
+
shouldDisplayAllAssociatedErrors,
|
|
1033
|
+
_options.shouldUseNativeValidation,
|
|
1034
|
+
)
|
|
1035
|
+
)[name];
|
|
1036
|
+
_updateIsValidating([name]);
|
|
1037
|
+
|
|
1038
|
+
_updateIsFieldValueUpdated(fieldValue);
|
|
1039
|
+
|
|
1040
|
+
if (isFieldValueUpdated) {
|
|
1041
|
+
if (error) {
|
|
1042
|
+
isValid = false;
|
|
1043
|
+
} else if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
|
|
1044
|
+
isValid = await executeBuiltInValidation({
|
|
1045
|
+
fields: _fields,
|
|
1046
|
+
onlyCheckValid: true,
|
|
1047
|
+
name: name as FieldPath<TFieldValues>,
|
|
1048
|
+
eventType: event.type,
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
if (isFieldValueUpdated) {
|
|
1055
|
+
field._f.deps &&
|
|
1056
|
+
(!Array.isArray(field._f.deps) || field._f.deps.length > 0) &&
|
|
1057
|
+
trigger(field._f.deps as FieldPath<TFieldValues> | FieldPath<TFieldValues>[]);
|
|
1058
|
+
shouldRenderByError(name, isValid, error, fieldState);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
|
|
1063
|
+
const _focusInput = (ref: Ref, key: string) => {
|
|
1064
|
+
if (get(_formState.errors, key) && ref.focus) {
|
|
1065
|
+
ref.focus();
|
|
1066
|
+
return 1;
|
|
1067
|
+
}
|
|
1068
|
+
return;
|
|
1069
|
+
};
|
|
1070
|
+
|
|
1071
|
+
const trigger: UseFormTrigger<TFieldValues> = async (name, options = {}) => {
|
|
1072
|
+
let isValid;
|
|
1073
|
+
let validationResult;
|
|
1074
|
+
const fieldNames = convertToArrayPayload(name) as InternalFieldName[];
|
|
1075
|
+
|
|
1076
|
+
if (_options.resolver) {
|
|
1077
|
+
const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
|
|
1078
|
+
|
|
1079
|
+
isValid = isEmptyObject(errors);
|
|
1080
|
+
validationResult = name ? !fieldNames.some((name) => get(errors, name)) : isValid;
|
|
1081
|
+
} else if (name) {
|
|
1082
|
+
validationResult = (
|
|
1083
|
+
await Promise.all(
|
|
1084
|
+
fieldNames.map(async (fieldName) => {
|
|
1085
|
+
const field = get(_fields, fieldName);
|
|
1086
|
+
return await executeBuiltInValidation({
|
|
1087
|
+
fields: field && field._f ? { [fieldName]: field } : field,
|
|
1088
|
+
eventType: EVENTS.TRIGGER,
|
|
1089
|
+
});
|
|
1090
|
+
}),
|
|
1091
|
+
)
|
|
1092
|
+
).every(Boolean);
|
|
1093
|
+
!(!validationResult && !_formState.isValid) && _setValid();
|
|
1094
|
+
} else {
|
|
1095
|
+
validationResult = isValid = await executeBuiltInValidation({
|
|
1096
|
+
fields: _fields,
|
|
1097
|
+
name,
|
|
1098
|
+
eventType: EVENTS.TRIGGER,
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
_subjects.state.next({
|
|
1103
|
+
...(!isString(name) ||
|
|
1104
|
+
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
1105
|
+
isValid !== _formState.isValid)
|
|
1106
|
+
? {}
|
|
1107
|
+
: { name }),
|
|
1108
|
+
...(_options.resolver || !name ? { isValid } : {}),
|
|
1109
|
+
errors: _formState.errors,
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
options.shouldFocus &&
|
|
1113
|
+
!validationResult &&
|
|
1114
|
+
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
|
1115
|
+
|
|
1116
|
+
return validationResult;
|
|
1117
|
+
};
|
|
1118
|
+
|
|
1119
|
+
const getValues: UseFormGetValues<TFieldValues> = (
|
|
1120
|
+
fieldNames?: FieldPath<TFieldValues> | ReadonlyArray<FieldPath<TFieldValues>>,
|
|
1121
|
+
config?: GetValuesConfig,
|
|
1122
|
+
) => {
|
|
1123
|
+
let values = {
|
|
1124
|
+
...(_state.mount ? _formValues : _defaultValues),
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
if (config) {
|
|
1128
|
+
values = extractFormValues(
|
|
1129
|
+
config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields,
|
|
1130
|
+
values,
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
return isUndefined(fieldNames)
|
|
1135
|
+
? values
|
|
1136
|
+
: isString(fieldNames)
|
|
1137
|
+
? get(values, fieldNames)
|
|
1138
|
+
: fieldNames.map((name) => get(values, name));
|
|
1139
|
+
};
|
|
1140
|
+
|
|
1141
|
+
const getFieldState: UseFormGetFieldState<TFieldValues> = (name, formState) => ({
|
|
1142
|
+
invalid: !!get((formState || _formState).errors, name),
|
|
1143
|
+
isDirty: !!get((formState || _formState).dirtyFields, name),
|
|
1144
|
+
error: get((formState || _formState).errors, name),
|
|
1145
|
+
isValidating: !!get(_formState.validatingFields, name),
|
|
1146
|
+
isTouched: !!get((formState || _formState).touchedFields, name),
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
const clearErrors: UseFormClearErrors<TFieldValues> = (name) => {
|
|
1150
|
+
const names = name ? convertToArrayPayload(name) : undefined;
|
|
1151
|
+
|
|
1152
|
+
names?.forEach((inputName) => unset(_formState.errors, inputName));
|
|
1153
|
+
|
|
1154
|
+
if (names) {
|
|
1155
|
+
names.forEach((inputName) => {
|
|
1156
|
+
_subjects.state.next({
|
|
1157
|
+
name: inputName,
|
|
1158
|
+
errors: _formState.errors,
|
|
1159
|
+
});
|
|
1160
|
+
});
|
|
1161
|
+
} else {
|
|
1162
|
+
_subjects.state.next({
|
|
1163
|
+
errors: {},
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
const setError: UseFormSetError<TFieldValues> = (name, error, options) => {
|
|
1169
|
+
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
1170
|
+
const currentError = get(_formState.errors, name) || {};
|
|
1171
|
+
|
|
1172
|
+
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
1173
|
+
|
|
1174
|
+
set(_formState.errors, name, {
|
|
1175
|
+
...restOfErrorTree,
|
|
1176
|
+
...error,
|
|
1177
|
+
ref,
|
|
1178
|
+
});
|
|
1179
|
+
|
|
1180
|
+
_subjects.state.next({
|
|
1181
|
+
name,
|
|
1182
|
+
errors: _formState.errors,
|
|
1183
|
+
isValid: false,
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
const watch: UseFormWatch<TFieldValues> = (
|
|
1190
|
+
name?:
|
|
1191
|
+
| FieldPath<TFieldValues>
|
|
1192
|
+
| ReadonlyArray<FieldPath<TFieldValues>>
|
|
1193
|
+
| WatchObserver<TFieldValues>,
|
|
1194
|
+
defaultValue?: DeepPartial<TFieldValues>,
|
|
1195
|
+
) => {
|
|
1196
|
+
if (isFunction(name)) {
|
|
1197
|
+
_valuesSubscriberCount++;
|
|
1198
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
1199
|
+
next: (payload) =>
|
|
1200
|
+
'values' in payload &&
|
|
1201
|
+
name(
|
|
1202
|
+
payload.values || _getWatch(undefined, defaultValue),
|
|
1203
|
+
payload as {
|
|
1204
|
+
name?: FieldPath<TFieldValues>;
|
|
1205
|
+
type?: EventType;
|
|
1206
|
+
value?: unknown;
|
|
1207
|
+
},
|
|
1208
|
+
),
|
|
1209
|
+
});
|
|
1210
|
+
let called = false;
|
|
1211
|
+
|
|
1212
|
+
return {
|
|
1213
|
+
unsubscribe: () => {
|
|
1214
|
+
if (called) {
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
called = true;
|
|
1219
|
+
_valuesSubscriberCount--;
|
|
1220
|
+
unsubscribe();
|
|
1221
|
+
},
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
return _getWatch(name as InternalFieldName | InternalFieldName[], defaultValue, true);
|
|
1225
|
+
};
|
|
1226
|
+
|
|
1227
|
+
const _subscribe: FromSubscribe<TFieldValues> = (props) => {
|
|
1228
|
+
const needsValues = !!(props.formState as Record<string, unknown>)?.values;
|
|
1229
|
+
if (needsValues) {
|
|
1230
|
+
_valuesSubscriberCount++;
|
|
1231
|
+
}
|
|
1232
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
1233
|
+
next: (
|
|
1234
|
+
formState: Partial<FormState<TFieldValues>> & {
|
|
1235
|
+
name?: InternalFieldName;
|
|
1236
|
+
values?: TFieldValues | undefined;
|
|
1237
|
+
type?: EventType;
|
|
1238
|
+
},
|
|
1239
|
+
) => {
|
|
1240
|
+
if (
|
|
1241
|
+
shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
1242
|
+
shouldRenderFormState(
|
|
1243
|
+
formState,
|
|
1244
|
+
(props.formState as ReadFormState) || _proxyFormState,
|
|
1245
|
+
_setFormState,
|
|
1246
|
+
props.reRenderRoot,
|
|
1247
|
+
)
|
|
1248
|
+
) {
|
|
1249
|
+
const snapshot = { ..._formValues } as TFieldValues;
|
|
1250
|
+
|
|
1251
|
+
props.callback({
|
|
1252
|
+
values: snapshot,
|
|
1253
|
+
..._formState,
|
|
1254
|
+
...formState,
|
|
1255
|
+
defaultValues: _defaultValues as FormState<TFieldValues>['defaultValues'],
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
});
|
|
1260
|
+
if (!needsValues) {
|
|
1261
|
+
return unsubscribe;
|
|
1262
|
+
}
|
|
1263
|
+
let called = false;
|
|
1264
|
+
return () => {
|
|
1265
|
+
if (called) {
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
called = true;
|
|
1270
|
+
_valuesSubscriberCount--;
|
|
1271
|
+
unsubscribe();
|
|
1272
|
+
};
|
|
1273
|
+
};
|
|
1274
|
+
|
|
1275
|
+
const subscribe: UseFormSubscribe<TFieldValues> = (props) => {
|
|
1276
|
+
_state.mount = true;
|
|
1277
|
+
_proxySubscribeFormState = {
|
|
1278
|
+
..._proxySubscribeFormState,
|
|
1279
|
+
...props.formState,
|
|
1280
|
+
};
|
|
1281
|
+
return _subscribe({
|
|
1282
|
+
...props,
|
|
1283
|
+
formState: {
|
|
1284
|
+
...defaultProxyFormState,
|
|
1285
|
+
...props.formState,
|
|
1286
|
+
},
|
|
1287
|
+
});
|
|
1288
|
+
};
|
|
1289
|
+
|
|
1290
|
+
const unregister: UseFormUnregister<TFieldValues> = (name, options = {}) => {
|
|
1291
|
+
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
|
1292
|
+
_names.mount.delete(fieldName);
|
|
1293
|
+
_names.array.delete(fieldName);
|
|
1294
|
+
|
|
1295
|
+
if (!options.keepValue) {
|
|
1296
|
+
unset(_fields, fieldName);
|
|
1297
|
+
unset(_formValues, fieldName);
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
!options.keepError && unset(_formState.errors, fieldName);
|
|
1301
|
+
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
|
1302
|
+
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
|
1303
|
+
!options.keepIsValidating && unset(_formState.validatingFields, fieldName);
|
|
1304
|
+
!_options.shouldUnregister && !options.keepDefaultValue && unset(_defaultValues, fieldName);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
_subjects.state.next({
|
|
1308
|
+
values: cloneObject(_formValues),
|
|
1309
|
+
});
|
|
1310
|
+
|
|
1311
|
+
_subjects.state.next({
|
|
1312
|
+
..._formState,
|
|
1313
|
+
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
|
1314
|
+
});
|
|
1315
|
+
|
|
1316
|
+
!options.keepIsValid && _setValid();
|
|
1317
|
+
};
|
|
1318
|
+
|
|
1319
|
+
const _setDisabledField: Control<TFieldValues>['_setDisabledField'] = ({ disabled, name }) => {
|
|
1320
|
+
if ((isBoolean(disabled) && _state.mount) || !!disabled || _names.disabled.has(name)) {
|
|
1321
|
+
const wasDisabled = _names.disabled.has(name);
|
|
1322
|
+
const isDisabled = !!disabled;
|
|
1323
|
+
const disabledStateChanged = wasDisabled !== isDisabled;
|
|
1324
|
+
|
|
1325
|
+
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
|
1326
|
+
disabledStateChanged && _state.mount && !_state.action && _setValid();
|
|
1327
|
+
}
|
|
1328
|
+
};
|
|
1329
|
+
|
|
1330
|
+
const register: UseFormRegister<TFieldValues> = (name, options = {}) => {
|
|
1331
|
+
let field = get(_fields, name);
|
|
1332
|
+
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
|
1333
|
+
const shouldRevalidateRemount =
|
|
1334
|
+
!_names.registerName.has(name) && field && field._f && !field._f.mount;
|
|
1335
|
+
|
|
1336
|
+
set(_fields, name, {
|
|
1337
|
+
...(field || {}),
|
|
1338
|
+
_f: {
|
|
1339
|
+
...(field && field._f ? field._f : { ref: { name } }),
|
|
1340
|
+
name,
|
|
1341
|
+
mount: true,
|
|
1342
|
+
...options,
|
|
1343
|
+
},
|
|
1344
|
+
});
|
|
1345
|
+
_names.mount.add(name);
|
|
1346
|
+
|
|
1347
|
+
if (field && !shouldRevalidateRemount) {
|
|
1348
|
+
_setDisabledField({
|
|
1349
|
+
disabled: isBoolean(options.disabled) ? options.disabled : _options.disabled,
|
|
1350
|
+
name,
|
|
1351
|
+
});
|
|
1352
|
+
} else {
|
|
1353
|
+
updateValidAndValue(name, true, options.value);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
return {
|
|
1357
|
+
...(disabledIsDefined ? { disabled: options.disabled || _options.disabled } : {}),
|
|
1358
|
+
...(_options.progressive
|
|
1359
|
+
? {
|
|
1360
|
+
required: !!options.required,
|
|
1361
|
+
min: getRuleValue(options.min),
|
|
1362
|
+
max: getRuleValue(options.max),
|
|
1363
|
+
minLength: getRuleValue<number>(options.minLength) as number,
|
|
1364
|
+
maxLength: getRuleValue(options.maxLength) as number,
|
|
1365
|
+
pattern: getRuleValue(options.pattern) as string,
|
|
1366
|
+
}
|
|
1367
|
+
: {}),
|
|
1368
|
+
name,
|
|
1369
|
+
// octane: upstream returns this handler as `onChange` — octane events are
|
|
1370
|
+
// native, so the per-keystroke handler is the platform `input` event. The
|
|
1371
|
+
// handler itself branches on event.type (blur/focusout vs everything
|
|
1372
|
+
// else), exactly as upstream.
|
|
1373
|
+
onInput: onChange,
|
|
1374
|
+
onBlur: onChange,
|
|
1375
|
+
ref: (ref: HTMLInputElement | null): void => {
|
|
1376
|
+
if (ref) {
|
|
1377
|
+
_names.registerName.add(name);
|
|
1378
|
+
register(name, options);
|
|
1379
|
+
_names.registerName.delete(name);
|
|
1380
|
+
field = get(_fields, name);
|
|
1381
|
+
|
|
1382
|
+
const fieldRef = isUndefined(ref.value)
|
|
1383
|
+
? ref.querySelectorAll
|
|
1384
|
+
? (ref.querySelectorAll('input,select,textarea')[0] as Ref) || ref
|
|
1385
|
+
: ref
|
|
1386
|
+
: ref;
|
|
1387
|
+
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
|
1388
|
+
const refs = field._f.refs || [];
|
|
1389
|
+
|
|
1390
|
+
if (
|
|
1391
|
+
radioOrCheckbox
|
|
1392
|
+
? refs.find((option: Ref) => option === fieldRef)
|
|
1393
|
+
: fieldRef === field._f.ref
|
|
1394
|
+
) {
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
set(_fields, name, {
|
|
1399
|
+
_f: {
|
|
1400
|
+
...field._f,
|
|
1401
|
+
...(radioOrCheckbox
|
|
1402
|
+
? {
|
|
1403
|
+
refs: [
|
|
1404
|
+
...refs.filter(live),
|
|
1405
|
+
fieldRef,
|
|
1406
|
+
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
|
1407
|
+
],
|
|
1408
|
+
ref: { type: fieldRef.type, name },
|
|
1409
|
+
}
|
|
1410
|
+
: { ref: fieldRef }),
|
|
1411
|
+
},
|
|
1412
|
+
});
|
|
1413
|
+
|
|
1414
|
+
updateValidAndValue(name, false, undefined, fieldRef);
|
|
1415
|
+
} else {
|
|
1416
|
+
field = get(_fields, name, {});
|
|
1417
|
+
|
|
1418
|
+
if (field._f) {
|
|
1419
|
+
field._f.mount = false;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
(_options.shouldUnregister || options.shouldUnregister) &&
|
|
1423
|
+
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
|
1424
|
+
_names.unMount.add(name);
|
|
1425
|
+
}
|
|
1426
|
+
},
|
|
1427
|
+
};
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
const _focusError = () =>
|
|
1431
|
+
_options.shouldFocusError &&
|
|
1432
|
+
!_options.shouldUseNativeValidation &&
|
|
1433
|
+
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
|
1434
|
+
|
|
1435
|
+
const _disableForm = (disabled?: boolean) => {
|
|
1436
|
+
if (isBoolean(disabled)) {
|
|
1437
|
+
_subjects.state.next({ disabled });
|
|
1438
|
+
iterateFieldsByAction(
|
|
1439
|
+
_fields,
|
|
1440
|
+
(ref, name) => {
|
|
1441
|
+
const currentField: Field = get(_fields, name);
|
|
1442
|
+
if (currentField) {
|
|
1443
|
+
ref.disabled = currentField._f.disabled || disabled;
|
|
1444
|
+
|
|
1445
|
+
if (Array.isArray(currentField._f.refs)) {
|
|
1446
|
+
currentField._f.refs.forEach((inputRef) => {
|
|
1447
|
+
inputRef.disabled = currentField._f.disabled || disabled;
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
},
|
|
1452
|
+
0,
|
|
1453
|
+
false,
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
const handleSubmit: UseFormHandleSubmit<TFieldValues, TTransformedValues> =
|
|
1459
|
+
(onValid, onInvalid) => async (e) => {
|
|
1460
|
+
let onValidError = undefined;
|
|
1461
|
+
if (e) {
|
|
1462
|
+
e.preventDefault && e.preventDefault();
|
|
1463
|
+
// octane: events are native; `persist` only exists on React's synthetic
|
|
1464
|
+
// events (kept for parity with upstream, harmlessly skipped here).
|
|
1465
|
+
(e as { persist?: () => void }).persist && (e as { persist?: () => void }).persist!();
|
|
1466
|
+
}
|
|
1467
|
+
let fieldValues: TFieldValues | TTransformedValues | Record<string, never> =
|
|
1468
|
+
cloneObject(_formValues);
|
|
1469
|
+
|
|
1470
|
+
_subjects.state.next({
|
|
1471
|
+
isSubmitting: true,
|
|
1472
|
+
});
|
|
1473
|
+
|
|
1474
|
+
if (_options.resolver) {
|
|
1475
|
+
const { errors, values } = await _runSchema();
|
|
1476
|
+
_updateIsValidating();
|
|
1477
|
+
_formState.errors = errors;
|
|
1478
|
+
fieldValues = cloneObject(values);
|
|
1479
|
+
} else {
|
|
1480
|
+
await executeBuiltInValidation({
|
|
1481
|
+
fields: _fields,
|
|
1482
|
+
eventType: EVENTS.SUBMIT,
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
if (_names.disabled.size) {
|
|
1487
|
+
for (const name of _names.disabled) {
|
|
1488
|
+
unset(fieldValues, name);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
unset(_formState.errors, ROOT_ERROR_TYPE);
|
|
1493
|
+
|
|
1494
|
+
if (isEmptyObject(_formState.errors)) {
|
|
1495
|
+
_subjects.state.next({
|
|
1496
|
+
errors: {},
|
|
1497
|
+
});
|
|
1498
|
+
try {
|
|
1499
|
+
await onValid(fieldValues as TTransformedValues, e);
|
|
1500
|
+
} catch (error) {
|
|
1501
|
+
onValidError = error;
|
|
1502
|
+
}
|
|
1503
|
+
} else {
|
|
1504
|
+
if (onInvalid) {
|
|
1505
|
+
await onInvalid({ ..._formState.errors }, e);
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
_focusError();
|
|
1509
|
+
setTimeout(_focusError);
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
_subjects.state.next({
|
|
1513
|
+
isSubmitted: true,
|
|
1514
|
+
isSubmitting: false,
|
|
1515
|
+
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
|
1516
|
+
submitCount: _formState.submitCount + 1,
|
|
1517
|
+
errors: _formState.errors,
|
|
1518
|
+
});
|
|
1519
|
+
if (onValidError) {
|
|
1520
|
+
throw onValidError;
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1523
|
+
|
|
1524
|
+
const resetField: UseFormResetField<TFieldValues> = (name, options = {}) => {
|
|
1525
|
+
if (get(_fields, name)) {
|
|
1526
|
+
if (isUndefined(options.defaultValue)) {
|
|
1527
|
+
setValue(name, cloneObject(get(_defaultValues, name)));
|
|
1528
|
+
} else {
|
|
1529
|
+
setValue(name, options.defaultValue as Parameters<typeof setValue<typeof name>>[1]);
|
|
1530
|
+
set(_defaultValues, name, cloneObject(options.defaultValue));
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
if (!options.keepTouched) {
|
|
1534
|
+
unset(_formState.touchedFields, name);
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
if (!options.keepDirty) {
|
|
1538
|
+
unset(_formState.dirtyFields, name);
|
|
1539
|
+
_formState.isDirty = options.defaultValue
|
|
1540
|
+
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
|
1541
|
+
: _getDirty();
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
if (!options.keepError) {
|
|
1545
|
+
unset(_formState.errors, name);
|
|
1546
|
+
_proxyFormState.isValid && _setValid();
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
_subjects.state.next({ ..._formState });
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1552
|
+
|
|
1553
|
+
const _reset: UseFormReset<TFieldValues> = (formValues, keepStateOptions = {}) => {
|
|
1554
|
+
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
|
|
1555
|
+
const cloneUpdatedValues = cloneObject(updatedValues);
|
|
1556
|
+
const isEmptyResetValues = isEmptyObject(formValues);
|
|
1557
|
+
const values = cloneUpdatedValues;
|
|
1558
|
+
const fieldRefs = _fields;
|
|
1559
|
+
|
|
1560
|
+
if (!keepStateOptions.keepDefaultValues) {
|
|
1561
|
+
_defaultValues = updatedValues;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
if (!keepStateOptions.keepValues) {
|
|
1565
|
+
if (keepStateOptions.keepDirtyValues) {
|
|
1566
|
+
const fieldsToCheck = new Set([
|
|
1567
|
+
..._names.mount,
|
|
1568
|
+
...Object.keys(getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)),
|
|
1569
|
+
]);
|
|
1570
|
+
for (const fieldName of Array.from(fieldsToCheck)) {
|
|
1571
|
+
const isDirty = get(_formState.dirtyFields, fieldName);
|
|
1572
|
+
const existingValue = get(_formValues, fieldName);
|
|
1573
|
+
const newValue = get(values, fieldName);
|
|
1574
|
+
|
|
1575
|
+
if (isDirty && !isUndefined(existingValue)) {
|
|
1576
|
+
set(values, fieldName, existingValue);
|
|
1577
|
+
} else if (!isDirty && !isUndefined(newValue)) {
|
|
1578
|
+
setValue(fieldName as FieldPath<TFieldValues>, newValue);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
} else {
|
|
1582
|
+
if (isWeb && isUndefined(formValues)) {
|
|
1583
|
+
for (const name of _names.mount) {
|
|
1584
|
+
const field = get(_fields, name);
|
|
1585
|
+
if (field && field._f) {
|
|
1586
|
+
const fieldReference = Array.isArray(field._f.refs) ? field._f.refs[0] : field._f.ref;
|
|
1587
|
+
|
|
1588
|
+
if (isHTMLElement(fieldReference)) {
|
|
1589
|
+
const form = fieldReference.closest('form');
|
|
1590
|
+
if (form) {
|
|
1591
|
+
form.reset();
|
|
1592
|
+
break;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
1600
|
+
for (const fieldName of _names.mount) {
|
|
1601
|
+
setValue(fieldName as FieldPath<TFieldValues>, get(values, fieldName));
|
|
1602
|
+
}
|
|
1603
|
+
} else {
|
|
1604
|
+
_fields = {};
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
if (_options.shouldUnregister) {
|
|
1609
|
+
_formValues = keepStateOptions.keepDefaultValues
|
|
1610
|
+
? (cloneObject(_defaultValues) as TFieldValues)
|
|
1611
|
+
: ({} as TFieldValues);
|
|
1612
|
+
|
|
1613
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
1614
|
+
for (const fieldName of _names.mount) {
|
|
1615
|
+
set(_formValues, fieldName, get(values, fieldName));
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
} else {
|
|
1619
|
+
_formValues = cloneObject(values) as TFieldValues;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
_subjects.array.next({
|
|
1623
|
+
values: { ...values },
|
|
1624
|
+
});
|
|
1625
|
+
|
|
1626
|
+
_subjects.state.next({
|
|
1627
|
+
name: undefined,
|
|
1628
|
+
type: undefined,
|
|
1629
|
+
values: { ...values } as TFieldValues,
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
_names = {
|
|
1634
|
+
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
|
|
1635
|
+
unMount: new Set(),
|
|
1636
|
+
array: new Set(),
|
|
1637
|
+
registerName: new Set(),
|
|
1638
|
+
disabled: new Set(),
|
|
1639
|
+
watch: new Set(),
|
|
1640
|
+
watchAll: false,
|
|
1641
|
+
focus: '',
|
|
1642
|
+
};
|
|
1643
|
+
|
|
1644
|
+
_state.mount =
|
|
1645
|
+
!_proxyFormState.isValid ||
|
|
1646
|
+
!!keepStateOptions.keepIsValid ||
|
|
1647
|
+
!!keepStateOptions.keepDirtyValues ||
|
|
1648
|
+
(!_options.shouldUnregister && !isEmptyObject(values));
|
|
1649
|
+
|
|
1650
|
+
_state.watch = !!_options.shouldUnregister;
|
|
1651
|
+
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
1652
|
+
_state.action = false;
|
|
1653
|
+
|
|
1654
|
+
if (!keepStateOptions.keepErrors) {
|
|
1655
|
+
_formState.errors = {};
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
_subjects.state.next({
|
|
1659
|
+
submitCount: keepStateOptions.keepSubmitCount ? _formState.submitCount : 0,
|
|
1660
|
+
isDirty: isEmptyResetValues
|
|
1661
|
+
? false
|
|
1662
|
+
: keepStateOptions.keepDirty
|
|
1663
|
+
? _formState.isDirty
|
|
1664
|
+
: keepStateOptions.keepValues
|
|
1665
|
+
? _getDirty()
|
|
1666
|
+
: !!(keepStateOptions.keepDefaultValues && !deepEqual(formValues, _defaultValues)),
|
|
1667
|
+
isSubmitted: keepStateOptions.keepIsSubmitted ? _formState.isSubmitted : false,
|
|
1668
|
+
dirtyFields: isEmptyResetValues
|
|
1669
|
+
? {}
|
|
1670
|
+
: keepStateOptions.keepDirtyValues
|
|
1671
|
+
? keepStateOptions.keepDefaultValues && _formValues
|
|
1672
|
+
? getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)
|
|
1673
|
+
: _formState.dirtyFields
|
|
1674
|
+
: keepStateOptions.keepDefaultValues && formValues
|
|
1675
|
+
? getDirtyFields(_defaultValues, formValues, undefined, fieldRefs)
|
|
1676
|
+
: keepStateOptions.keepDirty
|
|
1677
|
+
? _formState.dirtyFields
|
|
1678
|
+
: {},
|
|
1679
|
+
touchedFields: keepStateOptions.keepTouched ? _formState.touchedFields : {},
|
|
1680
|
+
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
|
1681
|
+
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
|
1682
|
+
? _formState.isSubmitSuccessful
|
|
1683
|
+
: false,
|
|
1684
|
+
isSubmitting: false,
|
|
1685
|
+
defaultValues: _defaultValues as FormState<TFieldValues>['defaultValues'],
|
|
1686
|
+
});
|
|
1687
|
+
};
|
|
1688
|
+
|
|
1689
|
+
const reset: UseFormReset<TFieldValues> = (formValues, keepStateOptions) =>
|
|
1690
|
+
_reset(
|
|
1691
|
+
isFunction(formValues) ? (formValues as Function)(_formValues as TFieldValues) : formValues,
|
|
1692
|
+
{ ..._options.resetOptions, ...keepStateOptions },
|
|
1693
|
+
);
|
|
1694
|
+
|
|
1695
|
+
const setFocus: UseFormSetFocus<TFieldValues> = (name, options = {}) => {
|
|
1696
|
+
const field = get(_fields, name);
|
|
1697
|
+
const fieldReference = field && field._f;
|
|
1698
|
+
|
|
1699
|
+
if (fieldReference) {
|
|
1700
|
+
const fieldRef = fieldReference.refs ? fieldReference.refs[0] : fieldReference.ref;
|
|
1701
|
+
|
|
1702
|
+
if (fieldRef.focus) {
|
|
1703
|
+
setTimeout(() => {
|
|
1704
|
+
fieldRef.focus();
|
|
1705
|
+
options.shouldSelect && isFunction(fieldRef.select) && fieldRef.select();
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
};
|
|
1710
|
+
|
|
1711
|
+
const _setFormState = (
|
|
1712
|
+
updatedFormState: Partial<FormState<TFieldValues>> & {
|
|
1713
|
+
name?: InternalFieldName;
|
|
1714
|
+
type?: EventType;
|
|
1715
|
+
values?: TFieldValues;
|
|
1716
|
+
},
|
|
1717
|
+
) => {
|
|
1718
|
+
// `name`, `type`, and `values` describe the event that produced this
|
|
1719
|
+
// update, not the form's persisted state (they aren't part of
|
|
1720
|
+
// `FormState`). Merging them in would leak a stale `name`/`type` from
|
|
1721
|
+
// one event into a later, unrelated notification that doesn't specify
|
|
1722
|
+
// its own.
|
|
1723
|
+
const { name, type, values, ...formState } = updatedFormState;
|
|
1724
|
+
|
|
1725
|
+
_formState = {
|
|
1726
|
+
..._formState,
|
|
1727
|
+
...formState,
|
|
1728
|
+
};
|
|
1729
|
+
};
|
|
1730
|
+
|
|
1731
|
+
const _resetDefaultValues = () =>
|
|
1732
|
+
isFunction(_options.defaultValues) &&
|
|
1733
|
+
(_options.defaultValues as Function)().then((values: TFieldValues) => {
|
|
1734
|
+
reset(values, _options.resetOptions);
|
|
1735
|
+
_subjects.state.next({
|
|
1736
|
+
isLoading: false,
|
|
1737
|
+
});
|
|
1738
|
+
});
|
|
1739
|
+
|
|
1740
|
+
const resetDefaultValues: UseFormResetDefaultValues<TFieldValues> = (values, options = {}) => {
|
|
1741
|
+
_defaultValues = cloneObject(values) as Partial<typeof _defaultValues>;
|
|
1742
|
+
|
|
1743
|
+
if (!options.keepDirty) {
|
|
1744
|
+
const newDirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
1745
|
+
_formState.dirtyFields = newDirtyFields as typeof _formState.dirtyFields;
|
|
1746
|
+
_formState.isDirty = !isEmptyObject(newDirtyFields);
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
if (!options.keepIsValid) {
|
|
1750
|
+
_setValid();
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
_subjects.state.next({
|
|
1754
|
+
..._formState,
|
|
1755
|
+
defaultValues: _defaultValues as FormState<TFieldValues>['defaultValues'],
|
|
1756
|
+
});
|
|
1757
|
+
};
|
|
1758
|
+
|
|
1759
|
+
const methods = {
|
|
1760
|
+
control: {
|
|
1761
|
+
register,
|
|
1762
|
+
unregister,
|
|
1763
|
+
getFieldState,
|
|
1764
|
+
handleSubmit,
|
|
1765
|
+
setError,
|
|
1766
|
+
_subscribe,
|
|
1767
|
+
_runSchema,
|
|
1768
|
+
_updateIsValidating,
|
|
1769
|
+
_focusError,
|
|
1770
|
+
_getWatch,
|
|
1771
|
+
_getDirty,
|
|
1772
|
+
_setValid,
|
|
1773
|
+
_setFieldArray,
|
|
1774
|
+
_setDisabledField,
|
|
1775
|
+
_setErrors,
|
|
1776
|
+
_getFieldArray,
|
|
1777
|
+
_reset,
|
|
1778
|
+
_resetDefaultValues,
|
|
1779
|
+
_removeUnmounted,
|
|
1780
|
+
_disableForm,
|
|
1781
|
+
_subjects,
|
|
1782
|
+
_proxyFormState,
|
|
1783
|
+
get _fields() {
|
|
1784
|
+
return _fields;
|
|
1785
|
+
},
|
|
1786
|
+
get _formValues() {
|
|
1787
|
+
return _formValues;
|
|
1788
|
+
},
|
|
1789
|
+
get _state() {
|
|
1790
|
+
return _state;
|
|
1791
|
+
},
|
|
1792
|
+
set _state(value) {
|
|
1793
|
+
_state = value;
|
|
1794
|
+
},
|
|
1795
|
+
get _defaultValues() {
|
|
1796
|
+
return _defaultValues;
|
|
1797
|
+
},
|
|
1798
|
+
get _names() {
|
|
1799
|
+
return _names;
|
|
1800
|
+
},
|
|
1801
|
+
set _names(value) {
|
|
1802
|
+
_names = value;
|
|
1803
|
+
},
|
|
1804
|
+
get _formState() {
|
|
1805
|
+
return _formState;
|
|
1806
|
+
},
|
|
1807
|
+
get _options() {
|
|
1808
|
+
return _options;
|
|
1809
|
+
},
|
|
1810
|
+
set _options(value) {
|
|
1811
|
+
_options = {
|
|
1812
|
+
..._options,
|
|
1813
|
+
...value,
|
|
1814
|
+
};
|
|
1815
|
+
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
1816
|
+
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1817
|
+
},
|
|
1818
|
+
},
|
|
1819
|
+
subscribe,
|
|
1820
|
+
trigger,
|
|
1821
|
+
register,
|
|
1822
|
+
handleSubmit,
|
|
1823
|
+
watch,
|
|
1824
|
+
setValue,
|
|
1825
|
+
setValues,
|
|
1826
|
+
getValues,
|
|
1827
|
+
reset,
|
|
1828
|
+
resetField,
|
|
1829
|
+
resetDefaultValues,
|
|
1830
|
+
clearErrors,
|
|
1831
|
+
unregister,
|
|
1832
|
+
setError,
|
|
1833
|
+
setFocus,
|
|
1834
|
+
getFieldState,
|
|
1835
|
+
};
|
|
1836
|
+
|
|
1837
|
+
return {
|
|
1838
|
+
...methods,
|
|
1839
|
+
formControl: methods,
|
|
1840
|
+
};
|
|
1841
|
+
}
|