@refinedev/react-hook-form 4.8.14 → 4.8.15
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/dist/esm/index.js.map +1 -1
- package/dist/iife/index.js +18 -18
- package/dist/iife/index.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/useForm/index.d.ts.map +1 -1
- package/dist/useModalForm/index.d.ts +13 -13
- package/dist/useModalForm/index.d.ts.map +1 -1
- package/dist/useStepsForm/index.d.ts +10 -10
- package/dist/useStepsForm/index.d.ts.map +1 -1
- package/package.json +32 -32
- package/src/index.ts +6 -6
- package/src/useForm/index.spec.tsx +210 -222
- package/src/useForm/index.ts +227 -229
- package/src/useModalForm/index.spec.ts +243 -243
- package/src/useModalForm/index.ts +256 -265
- package/src/useStepsForm/index.spec.ts +103 -107
- package/src/useStepsForm/index.ts +120 -120
package/src/useForm/index.ts
CHANGED
|
@@ -3,272 +3,270 @@ import get from "lodash/get";
|
|
|
3
3
|
import has from "lodash/has";
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
useForm as useHookForm,
|
|
7
|
+
UseFormProps as UseHookFormProps,
|
|
8
|
+
UseFormReturn,
|
|
9
|
+
FieldValues,
|
|
10
|
+
UseFormHandleSubmit,
|
|
11
|
+
Path,
|
|
12
12
|
} from "react-hook-form";
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
BaseRecord,
|
|
15
|
+
HttpError,
|
|
16
|
+
useForm as useFormCore,
|
|
17
|
+
useWarnAboutChange,
|
|
18
|
+
UseFormProps as UseFormCoreProps,
|
|
19
|
+
UseFormReturnType as UseFormReturnTypeCore,
|
|
20
|
+
useTranslate,
|
|
21
|
+
useRefineContext,
|
|
22
|
+
flattenObjectKeys,
|
|
23
23
|
} from "@refinedev/core";
|
|
24
24
|
|
|
25
25
|
export type UseFormReturnType<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
TQueryFnData extends BaseRecord = BaseRecord,
|
|
27
|
+
TError extends HttpError = HttpError,
|
|
28
|
+
TVariables extends FieldValues = FieldValues,
|
|
29
|
+
TContext extends object = {},
|
|
30
|
+
TData extends BaseRecord = TQueryFnData,
|
|
31
|
+
TResponse extends BaseRecord = TData,
|
|
32
|
+
TResponseError extends HttpError = TError,
|
|
33
33
|
> = UseFormReturn<TVariables, TContext> & {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
refineCore: UseFormReturnTypeCore<
|
|
35
|
+
TQueryFnData,
|
|
36
|
+
TError,
|
|
37
|
+
TVariables,
|
|
38
|
+
TData,
|
|
39
|
+
TResponse,
|
|
40
|
+
TResponseError
|
|
41
|
+
>;
|
|
42
|
+
saveButtonProps: {
|
|
43
|
+
disabled: boolean;
|
|
44
|
+
onClick: (e: React.BaseSyntheticEvent) => void;
|
|
45
|
+
};
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
export type UseFormProps<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
TQueryFnData extends BaseRecord = BaseRecord,
|
|
50
|
+
TError extends HttpError = HttpError,
|
|
51
|
+
TVariables extends FieldValues = FieldValues,
|
|
52
|
+
TContext extends object = {},
|
|
53
|
+
TData extends BaseRecord = TQueryFnData,
|
|
54
|
+
TResponse extends BaseRecord = TData,
|
|
55
|
+
TResponseError extends HttpError = TError,
|
|
56
56
|
> = {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
TQueryFnData,
|
|
63
|
-
TError,
|
|
64
|
-
TVariables,
|
|
65
|
-
TData,
|
|
66
|
-
TResponse,
|
|
67
|
-
TResponseError
|
|
68
|
-
>;
|
|
69
|
-
/**
|
|
70
|
-
* When you have unsaved changes and try to leave the current page, **refine** shows a confirmation modal box.
|
|
71
|
-
* @default `false*`
|
|
72
|
-
*/
|
|
73
|
-
warnWhenUnsavedChanges?: boolean;
|
|
74
|
-
/**
|
|
75
|
-
* Disables server-side validation
|
|
76
|
-
* @default false
|
|
77
|
-
* @see {@link https://refine.dev/docs/advanced-tutorials/forms/server-side-form-validation/}
|
|
78
|
-
*/
|
|
79
|
-
disableServerSideValidation?: boolean;
|
|
80
|
-
} & UseHookFormProps<TVariables, TContext>;
|
|
81
|
-
|
|
82
|
-
export const useForm = <
|
|
83
|
-
TQueryFnData extends BaseRecord = BaseRecord,
|
|
84
|
-
TError extends HttpError = HttpError,
|
|
85
|
-
TVariables extends FieldValues = FieldValues,
|
|
86
|
-
TContext extends object = {},
|
|
87
|
-
TData extends BaseRecord = TQueryFnData,
|
|
88
|
-
TResponse extends BaseRecord = TData,
|
|
89
|
-
TResponseError extends HttpError = TError,
|
|
90
|
-
>({
|
|
91
|
-
refineCoreProps,
|
|
92
|
-
warnWhenUnsavedChanges: warnWhenUnsavedChangesProp,
|
|
93
|
-
disableServerSideValidation: disableServerSideValidationProp = false,
|
|
94
|
-
...rest
|
|
95
|
-
}: UseFormProps<
|
|
57
|
+
/**
|
|
58
|
+
* Configuration object for the core of the [useForm](/docs/api-reference/core/hooks/useForm/)
|
|
59
|
+
* @type [`UseFormCoreProps<TQueryFnData, TError, TVariables, TData, TResponse, TResponseError>`](/docs/api-reference/core/hooks/useForm/#properties)
|
|
60
|
+
*/
|
|
61
|
+
refineCoreProps?: UseFormCoreProps<
|
|
96
62
|
TQueryFnData,
|
|
97
63
|
TError,
|
|
98
64
|
TVariables,
|
|
99
|
-
TContext,
|
|
100
65
|
TData,
|
|
101
66
|
TResponse,
|
|
102
67
|
TResponseError
|
|
68
|
+
>;
|
|
69
|
+
/**
|
|
70
|
+
* When you have unsaved changes and try to leave the current page, **refine** shows a confirmation modal box.
|
|
71
|
+
* @default `false*`
|
|
72
|
+
*/
|
|
73
|
+
warnWhenUnsavedChanges?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Disables server-side validation
|
|
76
|
+
* @default false
|
|
77
|
+
* @see {@link https://refine.dev/docs/advanced-tutorials/forms/server-side-form-validation/}
|
|
78
|
+
*/
|
|
79
|
+
disableServerSideValidation?: boolean;
|
|
80
|
+
} & UseHookFormProps<TVariables, TContext>;
|
|
81
|
+
|
|
82
|
+
export const useForm = <
|
|
83
|
+
TQueryFnData extends BaseRecord = BaseRecord,
|
|
84
|
+
TError extends HttpError = HttpError,
|
|
85
|
+
TVariables extends FieldValues = FieldValues,
|
|
86
|
+
TContext extends object = {},
|
|
87
|
+
TData extends BaseRecord = TQueryFnData,
|
|
88
|
+
TResponse extends BaseRecord = TData,
|
|
89
|
+
TResponseError extends HttpError = TError,
|
|
90
|
+
>({
|
|
91
|
+
refineCoreProps,
|
|
92
|
+
warnWhenUnsavedChanges: warnWhenUnsavedChangesProp,
|
|
93
|
+
disableServerSideValidation: disableServerSideValidationProp = false,
|
|
94
|
+
...rest
|
|
95
|
+
}: UseFormProps<
|
|
96
|
+
TQueryFnData,
|
|
97
|
+
TError,
|
|
98
|
+
TVariables,
|
|
99
|
+
TContext,
|
|
100
|
+
TData,
|
|
101
|
+
TResponse,
|
|
102
|
+
TResponseError
|
|
103
103
|
> = {}): UseFormReturnType<
|
|
104
|
+
TQueryFnData,
|
|
105
|
+
TError,
|
|
106
|
+
TVariables,
|
|
107
|
+
TContext,
|
|
108
|
+
TData,
|
|
109
|
+
TResponse,
|
|
110
|
+
TResponseError
|
|
111
|
+
> => {
|
|
112
|
+
const { options } = useRefineContext();
|
|
113
|
+
const disableServerSideValidation =
|
|
114
|
+
options?.disableServerSideValidation || disableServerSideValidationProp;
|
|
115
|
+
|
|
116
|
+
const translate = useTranslate();
|
|
117
|
+
|
|
118
|
+
const { warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine, setWarnWhen } =
|
|
119
|
+
useWarnAboutChange();
|
|
120
|
+
const warnWhenUnsavedChanges =
|
|
121
|
+
warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine;
|
|
122
|
+
|
|
123
|
+
const useHookFormResult = useHookForm<TVariables, TContext>({
|
|
124
|
+
...rest,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const {
|
|
128
|
+
watch,
|
|
129
|
+
setValue,
|
|
130
|
+
getValues,
|
|
131
|
+
handleSubmit: handleSubmitReactHookForm,
|
|
132
|
+
setError,
|
|
133
|
+
} = useHookFormResult;
|
|
134
|
+
|
|
135
|
+
const useFormCoreResult = useFormCore<
|
|
104
136
|
TQueryFnData,
|
|
105
137
|
TError,
|
|
106
138
|
TVariables,
|
|
107
|
-
TContext,
|
|
108
139
|
TData,
|
|
109
140
|
TResponse,
|
|
110
141
|
TResponseError
|
|
111
|
-
>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
142
|
+
>({
|
|
143
|
+
...refineCoreProps,
|
|
144
|
+
onMutationError: (error, _variables, _context) => {
|
|
145
|
+
if (disableServerSideValidation) {
|
|
146
|
+
refineCoreProps?.onMutationError?.(error, _variables, _context);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const errors = error?.errors;
|
|
151
|
+
|
|
152
|
+
for (const key in errors) {
|
|
153
|
+
// when the key is not registered in the form, react-hook-form not working
|
|
154
|
+
const isKeyInVariables = Object.keys(
|
|
155
|
+
flattenObjectKeys(_variables),
|
|
156
|
+
).includes(key);
|
|
157
|
+
|
|
158
|
+
if (!isKeyInVariables) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
115
161
|
|
|
116
|
-
|
|
162
|
+
const fieldError = errors[key];
|
|
117
163
|
|
|
118
|
-
|
|
119
|
-
warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine,
|
|
120
|
-
setWarnWhen,
|
|
121
|
-
} = useWarnAboutChange();
|
|
122
|
-
const warnWhenUnsavedChanges =
|
|
123
|
-
warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine;
|
|
164
|
+
let newError = "";
|
|
124
165
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
166
|
+
if (Array.isArray(fieldError)) {
|
|
167
|
+
newError = fieldError.join(" ");
|
|
168
|
+
}
|
|
128
169
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
getValues,
|
|
133
|
-
handleSubmit: handleSubmitReactHookForm,
|
|
134
|
-
setError,
|
|
135
|
-
} = useHookFormResult;
|
|
136
|
-
|
|
137
|
-
const useFormCoreResult = useFormCore<
|
|
138
|
-
TQueryFnData,
|
|
139
|
-
TError,
|
|
140
|
-
TVariables,
|
|
141
|
-
TData,
|
|
142
|
-
TResponse,
|
|
143
|
-
TResponseError
|
|
144
|
-
>({
|
|
145
|
-
...refineCoreProps,
|
|
146
|
-
onMutationError: (error, _variables, _context) => {
|
|
147
|
-
if (disableServerSideValidation) {
|
|
148
|
-
refineCoreProps?.onMutationError?.(error, _variables, _context);
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const errors = error?.errors;
|
|
153
|
-
|
|
154
|
-
for (const key in errors) {
|
|
155
|
-
// when the key is not registered in the form, react-hook-form not working
|
|
156
|
-
const isKeyInVariables = Object.keys(
|
|
157
|
-
flattenObjectKeys(_variables),
|
|
158
|
-
).includes(key);
|
|
159
|
-
|
|
160
|
-
if (!isKeyInVariables) {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const fieldError = errors[key];
|
|
165
|
-
|
|
166
|
-
let newError = "";
|
|
167
|
-
|
|
168
|
-
if (Array.isArray(fieldError)) {
|
|
169
|
-
newError = fieldError.join(" ");
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (typeof fieldError === "string") {
|
|
173
|
-
newError = fieldError;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (typeof fieldError === "boolean" && fieldError) {
|
|
177
|
-
newError = "Field is not valid.";
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (typeof fieldError === "object" && "key" in fieldError) {
|
|
181
|
-
const translatedMessage = translate(
|
|
182
|
-
fieldError.key,
|
|
183
|
-
fieldError.message,
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
newError = translatedMessage;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
setError(key as Path<TVariables>, {
|
|
190
|
-
message: newError,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
refineCoreProps?.onMutationError?.(error, _variables, _context);
|
|
195
|
-
},
|
|
196
|
-
});
|
|
170
|
+
if (typeof fieldError === "string") {
|
|
171
|
+
newError = fieldError;
|
|
172
|
+
}
|
|
197
173
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
useEffect(() => {
|
|
202
|
-
const data = queryResult?.data?.data;
|
|
203
|
-
if (!data) return;
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* get registered fields from react-hook-form
|
|
207
|
-
*/
|
|
208
|
-
const registeredFields = Object.keys(flattenObjectKeys(getValues()));
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* set values from query result as default values
|
|
212
|
-
*/
|
|
213
|
-
registeredFields.forEach((path) => {
|
|
214
|
-
const hasValue = has(data, path);
|
|
215
|
-
const dataValue = get(data, path);
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* set value if the path exists in the query result even if the value is null
|
|
219
|
-
*/
|
|
220
|
-
if (hasValue) {
|
|
221
|
-
setValue(path as Path<TVariables>, dataValue);
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
}, [queryResult?.data, setValue, getValues]);
|
|
174
|
+
if (typeof fieldError === "boolean" && fieldError) {
|
|
175
|
+
newError = "Field is not valid.";
|
|
176
|
+
}
|
|
225
177
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
});
|
|
232
|
-
return () => subscription.unsubscribe();
|
|
233
|
-
}, [watch]);
|
|
178
|
+
if (typeof fieldError === "object" && "key" in fieldError) {
|
|
179
|
+
const translatedMessage = translate(
|
|
180
|
+
fieldError.key,
|
|
181
|
+
fieldError.message,
|
|
182
|
+
);
|
|
234
183
|
|
|
235
|
-
|
|
236
|
-
if (warnWhenUnsavedChanges) {
|
|
237
|
-
setWarnWhen(true);
|
|
184
|
+
newError = translatedMessage;
|
|
238
185
|
}
|
|
239
186
|
|
|
240
|
-
|
|
241
|
-
|
|
187
|
+
setError(key as Path<TVariables>, {
|
|
188
|
+
message: newError,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
242
191
|
|
|
243
|
-
|
|
192
|
+
refineCoreProps?.onMutationError?.(error, _variables, _context);
|
|
193
|
+
},
|
|
194
|
+
});
|
|
244
195
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
196
|
+
const { queryResult, onFinish, formLoading, onFinishAutoSave } =
|
|
197
|
+
useFormCoreResult;
|
|
248
198
|
|
|
249
|
-
|
|
250
|
-
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
const data = queryResult?.data?.data;
|
|
201
|
+
if (!data) return;
|
|
251
202
|
|
|
252
|
-
|
|
253
|
-
|
|
203
|
+
/**
|
|
204
|
+
* get registered fields from react-hook-form
|
|
205
|
+
*/
|
|
206
|
+
const registeredFields = Object.keys(flattenObjectKeys(getValues()));
|
|
254
207
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
208
|
+
/**
|
|
209
|
+
* set values from query result as default values
|
|
210
|
+
*/
|
|
211
|
+
registeredFields.forEach((path) => {
|
|
212
|
+
const hasValue = has(data, path);
|
|
213
|
+
const dataValue = get(data, path);
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* set value if the path exists in the query result even if the value is null
|
|
217
|
+
*/
|
|
218
|
+
if (hasValue) {
|
|
219
|
+
setValue(path as Path<TVariables>, dataValue);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}, [queryResult?.data, setValue, getValues]);
|
|
223
|
+
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
const subscription = watch((values: any, { type }: { type?: any }) => {
|
|
226
|
+
if (type === "change") {
|
|
227
|
+
onValuesChange(values);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
return () => subscription.unsubscribe();
|
|
231
|
+
}, [watch]);
|
|
232
|
+
|
|
233
|
+
const onValuesChange = (changeValues: TVariables) => {
|
|
234
|
+
if (warnWhenUnsavedChanges) {
|
|
235
|
+
setWarnWhen(true);
|
|
236
|
+
}
|
|
267
237
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
238
|
+
if (refineCoreProps?.autoSave) {
|
|
239
|
+
setWarnWhen(false);
|
|
240
|
+
|
|
241
|
+
const onFinishProps = refineCoreProps.autoSave?.onFinish;
|
|
242
|
+
|
|
243
|
+
if (onFinishProps) {
|
|
244
|
+
return onFinishAutoSave(onFinishProps(changeValues));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return onFinishAutoSave(changeValues);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return changeValues;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const handleSubmit: UseFormHandleSubmit<TVariables> =
|
|
254
|
+
(onValid, onInvalid) => async (e) => {
|
|
255
|
+
setWarnWhen(false);
|
|
256
|
+
return handleSubmitReactHookForm(onValid, onInvalid)(e);
|
|
273
257
|
};
|
|
258
|
+
|
|
259
|
+
const saveButtonProps = {
|
|
260
|
+
disabled: formLoading,
|
|
261
|
+
onClick: (e: React.BaseSyntheticEvent) => {
|
|
262
|
+
handleSubmit(onFinish, () => false)(e);
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
...useHookFormResult,
|
|
268
|
+
handleSubmit,
|
|
269
|
+
refineCore: useFormCoreResult,
|
|
270
|
+
saveButtonProps,
|
|
271
|
+
};
|
|
274
272
|
};
|