react-form-manage 1.0.8-beta.22 → 1.0.8-beta.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/components/Form/FormItem.d.ts +2 -1
- package/dist/components/Form/FormItem.js +4 -2
- package/dist/hooks/useFormItemControl.d.ts +3 -1
- package/dist/hooks/useFormItemControl.js +5 -5
- package/dist/hooks/useFormListControl.js +18 -0
- package/dist/providers/Form.d.ts +4 -1
- package/dist/providers/Form.js +15 -3
- package/dist/stores/formStore.d.ts +17 -2
- package/dist/stores/formStore.js +12 -2
- package/package.json +1 -1
- package/src/App.tsx +6 -2
- package/src/components/Form/FormItem.tsx +4 -0
- package/src/hooks/useFormItemControl.ts +20 -4
- package/src/hooks/useFormListControl.ts +18 -3
- package/src/providers/Form.tsx +29 -4
- package/src/stores/formStore.ts +34 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.0.8-beta.23] - 2026-02-04
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
- Add `hidden` prop to FormItem for conditional visibility control
|
|
9
|
+
- Add `collectHiddenValue` option to control whether hidden form items contribute to form data collection
|
|
10
|
+
- FormItem can now be retrieved from Form instance
|
|
11
|
+
- Enhanced form item state management with visibility tracking
|
|
12
|
+
|
|
5
13
|
## [1.0.8-beta.22] - 2026-02-02
|
|
6
14
|
|
|
7
15
|
### Changes
|
|
@@ -11,5 +11,6 @@ export interface FormItemProps {
|
|
|
11
11
|
getValueFromEvent?: (...args: any[]) => any;
|
|
12
12
|
controlAfterInit?: boolean;
|
|
13
13
|
hidden?: boolean;
|
|
14
|
+
collectOnHidden?: boolean;
|
|
14
15
|
}
|
|
15
|
-
export default function FormItem({ children, name, formName, initialValue, formItemId: externalFormItemId, rules, valuePropName, getValueFromEvent, controlAfterInit, hidden, }: FormItemProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export default function FormItem({ children, name, formName, initialValue, formItemId: externalFormItemId, rules, valuePropName, getValueFromEvent, controlAfterInit, hidden, collectOnHidden, }: FormItemProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { cloneElement, Fragment, useRef, useState } from "react";
|
|
3
3
|
import { v4 } from "uuid";
|
|
4
4
|
import useFormItemControl from "../../hooks/useFormItemControl";
|
|
5
|
-
function FormItem({ children, name, formName, initialValue, formItemId: externalFormItemId, rules, valuePropName = "value", getValueFromEvent, controlAfterInit = false, hidden }) {
|
|
5
|
+
function FormItem({ children, name, formName, initialValue, formItemId: externalFormItemId, rules, valuePropName = "value", getValueFromEvent, controlAfterInit = false, hidden, collectOnHidden }) {
|
|
6
6
|
const elRef = useRef(null);
|
|
7
7
|
const [formItemId] = useState(externalFormItemId != null ? externalFormItemId : v4());
|
|
8
8
|
const { value, onChange, errors, state, onFocus, isDirty, submitState, isTouched, isInitied } = useFormItemControl({
|
|
@@ -11,7 +11,9 @@ function FormItem({ children, name, formName, initialValue, formItemId: external
|
|
|
11
11
|
initialValue,
|
|
12
12
|
formItemId,
|
|
13
13
|
rules,
|
|
14
|
-
elementRef: elRef
|
|
14
|
+
elementRef: elRef,
|
|
15
|
+
hidden,
|
|
16
|
+
collectOnHidden
|
|
15
17
|
});
|
|
16
18
|
return _jsx(Fragment, { children: !hidden && children ? cloneElement(children, {
|
|
17
19
|
name,
|
|
@@ -10,6 +10,8 @@ interface UseFormItemControlProps {
|
|
|
10
10
|
formItemId?: string;
|
|
11
11
|
rules?: ValidationRule[];
|
|
12
12
|
elementRef?: RefObject<any> | null;
|
|
13
|
+
hidden?: boolean;
|
|
14
|
+
collectOnHidden?: boolean;
|
|
13
15
|
}
|
|
14
16
|
export interface UseFormItemControlReturn {
|
|
15
17
|
value: any;
|
|
@@ -22,5 +24,5 @@ export interface UseFormItemControlReturn {
|
|
|
22
24
|
submitState?: SubmitState;
|
|
23
25
|
isInitied?: boolean;
|
|
24
26
|
}
|
|
25
|
-
export default function useFormItemControl<T = any>({ formName, form, name, initialValue, formItemId, rules, elementRef, }: UseFormItemControlProps): UseFormItemControlReturn;
|
|
27
|
+
export default function useFormItemControl<T = any>({ formName, form, name, initialValue, formItemId, rules, elementRef, hidden, collectOnHidden, }: UseFormItemControlProps): UseFormItemControlReturn;
|
|
26
28
|
export {};
|
|
@@ -6,7 +6,7 @@ import { IS_ALPHABET_STRING_AND_NUMBER_REGEX, IS_EMAIL_REGEX, IS_NAME_REGEX, IS_
|
|
|
6
6
|
import { useFormContext } from "../providers/Form";
|
|
7
7
|
import { useFormStore } from "../stores/formStore";
|
|
8
8
|
const VALID_PREMITIVE_TYPE = ["string", "number", "undefined"];
|
|
9
|
-
function useFormItemControl({ formName, form, name, initialValue, formItemId, rules, elementRef }) {
|
|
9
|
+
function useFormItemControl({ formName, form, name, initialValue, formItemId, rules, elementRef, hidden, collectOnHidden }) {
|
|
10
10
|
const contextForm = useFormContext();
|
|
11
11
|
const {
|
|
12
12
|
value,
|
|
@@ -88,8 +88,6 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
88
88
|
const internalRules = useMemo(() => {
|
|
89
89
|
return rules || [];
|
|
90
90
|
}, [rules]);
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
}, [value, listener]);
|
|
93
91
|
const { data: errors, state } = useTaskEffect({
|
|
94
92
|
async task() {
|
|
95
93
|
const listErrors = [];
|
|
@@ -304,11 +302,13 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
304
302
|
emitFocus,
|
|
305
303
|
isTouched: false,
|
|
306
304
|
isDirty: false,
|
|
307
|
-
isInitied:
|
|
305
|
+
isInitied: false,
|
|
308
306
|
name,
|
|
309
307
|
formName: formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName),
|
|
310
308
|
formItemId,
|
|
311
|
-
onReset
|
|
309
|
+
onReset,
|
|
310
|
+
hidden,
|
|
311
|
+
collectOnHidden
|
|
312
312
|
});
|
|
313
313
|
}
|
|
314
314
|
return () => {
|
|
@@ -194,6 +194,12 @@ function useFormListControl({ name, form, initialValues, formName }) {
|
|
|
194
194
|
});
|
|
195
195
|
setListFields(result);
|
|
196
196
|
setCacheData(formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName), name, listFormInitValues);
|
|
197
|
+
if (getListener(formItemId)) {
|
|
198
|
+
setListener({
|
|
199
|
+
formItemId,
|
|
200
|
+
isInitied: true
|
|
201
|
+
});
|
|
202
|
+
}
|
|
197
203
|
return;
|
|
198
204
|
}
|
|
199
205
|
if (Array.isArray(internalInitValue)) {
|
|
@@ -207,6 +213,12 @@ function useFormListControl({ name, form, initialValues, formName }) {
|
|
|
207
213
|
});
|
|
208
214
|
setListFields(result);
|
|
209
215
|
setListFormInitValues(internalInitValue);
|
|
216
|
+
if (getListener(formItemId)) {
|
|
217
|
+
setListener({
|
|
218
|
+
formItemId,
|
|
219
|
+
isInitied: true
|
|
220
|
+
});
|
|
221
|
+
}
|
|
210
222
|
return;
|
|
211
223
|
}
|
|
212
224
|
if (Array.isArray(initialValues)) {
|
|
@@ -223,6 +235,12 @@ function useFormListControl({ name, form, initialValues, formName }) {
|
|
|
223
235
|
}
|
|
224
236
|
setListFields(result);
|
|
225
237
|
setListFormInitValues(initialValues);
|
|
238
|
+
if (getListener(formItemId)) {
|
|
239
|
+
setListener({
|
|
240
|
+
formItemId,
|
|
241
|
+
isInitied: true
|
|
242
|
+
});
|
|
243
|
+
}
|
|
226
244
|
return;
|
|
227
245
|
}
|
|
228
246
|
}
|
package/dist/providers/Form.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { ComponentType, FormHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import FormItem from "../components/Form/FormItem";
|
|
2
3
|
import type { PublicFormInstance, UseFormItemStateWatchReturn } from "../types/public";
|
|
3
4
|
export type { FormFieldError, SubmitState, UseFormItemStateWatchReturn, ValidationRule, } from "../types/public";
|
|
4
5
|
export declare const FormContext: import("react").Context<any>;
|
|
5
6
|
export interface FormProps<T = any> extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
|
|
7
|
+
collectHiddenFields?: boolean;
|
|
6
8
|
children: ReactNode;
|
|
7
9
|
formName: string;
|
|
8
10
|
initialValues?: T;
|
|
@@ -15,9 +17,10 @@ export interface FormProps<T = any> extends Omit<FormHTMLAttributes<HTMLFormElem
|
|
|
15
17
|
}) => void | Promise<void>;
|
|
16
18
|
FormElement?: ComponentType<any>;
|
|
17
19
|
}
|
|
18
|
-
declare function Form<T = any>({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, ...props }: FormProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
declare function Form<T = any>({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, collectHiddenFields: formCollectHiddenFields, ...props }: FormProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
19
21
|
declare namespace Form {
|
|
20
22
|
var useForm: typeof import("./Form").useForm;
|
|
23
|
+
var Item: typeof FormItem;
|
|
21
24
|
var useWatch: typeof import("./Form").useWatch;
|
|
22
25
|
var useSubmitDataWatch: typeof import("./Form").useSubmitDataWatch;
|
|
23
26
|
var useFormStateWatch: <T = any>(formNameOrFormInstance?: string | PublicFormInstance<T>) => any;
|
package/dist/providers/Form.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cloneDeep, get, isEqual, isNil, isPlainObject, last, set, uniqBy } from "lodash";
|
|
2
|
+
import { cloneDeep, filter, get, isEqual, isNil, isPlainObject, last, set, uniqBy } from "lodash";
|
|
3
3
|
import { useTask } from "minh-custom-hooks-release";
|
|
4
4
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
5
5
|
import { flushSync } from "react-dom";
|
|
6
6
|
import { useShallow } from "zustand/react/shallow";
|
|
7
7
|
import FormCleanUp from "../components/Form/FormCleanUp";
|
|
8
|
+
import FormItem from "../components/Form/FormItem";
|
|
8
9
|
import { SUBMIT_STATE } from "../constants/form";
|
|
9
10
|
import { useFormStore } from "../stores/formStore";
|
|
10
11
|
import { getAllNoneObjStringPath } from "../utils/obj.util";
|
|
11
12
|
const FormContext = createContext(null);
|
|
12
|
-
function Form({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, ...props }) {
|
|
13
|
+
function Form({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, collectHiddenFields: formCollectHiddenFields = true, ...props }) {
|
|
13
14
|
const {
|
|
14
15
|
// appInitValue,
|
|
15
16
|
getFormItemValue,
|
|
@@ -150,7 +151,17 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
150
151
|
const formValues = getFormValues(formName);
|
|
151
152
|
const resultValues = cloneDeep(formValues);
|
|
152
153
|
const cleanValues = {};
|
|
153
|
-
uniqBy(listeners, (l) =>
|
|
154
|
+
uniqBy(filter(listeners, (l) => {
|
|
155
|
+
if (!l.hidden)
|
|
156
|
+
return true;
|
|
157
|
+
if (isNil(props2 == null ? void 0 : props2.collectHiddenFields)) {
|
|
158
|
+
if (isNil(l.collectOnHidden)) {
|
|
159
|
+
return formCollectHiddenFields;
|
|
160
|
+
}
|
|
161
|
+
return Boolean(l.collectOnHidden);
|
|
162
|
+
}
|
|
163
|
+
return props2.collectHiddenFields;
|
|
164
|
+
}), (l) => l.name).forEach((l) => {
|
|
154
165
|
set(cleanValues, l.name, get(resultValues, l.name));
|
|
155
166
|
});
|
|
156
167
|
const handleIsolateCase = async () => {
|
|
@@ -356,6 +367,7 @@ const useFormItemStateWatch = (nameOrFormItemId, formNameOrFormInstance) => {
|
|
|
356
367
|
};
|
|
357
368
|
};
|
|
358
369
|
Form.useForm = useForm;
|
|
370
|
+
Form.Item = FormItem;
|
|
359
371
|
Form.useWatch = useWatch;
|
|
360
372
|
Form.useSubmitDataWatch = useSubmitDataWatch;
|
|
361
373
|
Form.useFormStateWatch = useFormStateWatch;
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
type ListenerFormItemType = "normal" | "array";
|
|
2
|
-
export interface
|
|
2
|
+
export interface SubmitProps<T = any> {
|
|
3
|
+
externalFinishCallback?: (values: T, allValues?: any) => void | Promise<void>;
|
|
4
|
+
externalRejectCallback?: (errorFields: any[]) => void | Promise<void>;
|
|
5
|
+
externalFinallyCallback?: (result: {
|
|
6
|
+
errorsField: any[];
|
|
7
|
+
values: T;
|
|
8
|
+
withUnRegisteredValues: any;
|
|
9
|
+
}) => void | Promise<void>;
|
|
10
|
+
callBothFinish?: boolean;
|
|
11
|
+
callBothReject?: boolean;
|
|
12
|
+
callBothFinally?: boolean;
|
|
13
|
+
collectHiddenFields?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface FormInstance<T = any> {
|
|
3
16
|
formName: string;
|
|
4
17
|
resetFields: (values?: any) => void;
|
|
5
|
-
submit: (
|
|
18
|
+
submit: (props?: SubmitProps<T>) => void;
|
|
6
19
|
submitAsync: (values?: any) => Promise<any>;
|
|
7
20
|
setFieldValue: (name: string, value: any, options?: any) => void;
|
|
8
21
|
setFieldValues: (values: Record<string, any>, options?: any) => void;
|
|
@@ -28,6 +41,8 @@ export interface ListenerItem {
|
|
|
28
41
|
emitFocus?: any;
|
|
29
42
|
isInitied?: boolean;
|
|
30
43
|
type?: ListenerFormItemType;
|
|
44
|
+
hidden?: boolean;
|
|
45
|
+
collectOnHidden?: boolean;
|
|
31
46
|
}
|
|
32
47
|
export interface CleanUpItem {
|
|
33
48
|
name?: string;
|
package/dist/stores/formStore.js
CHANGED
|
@@ -200,7 +200,7 @@ const createListenersSlice = (storeSet, storeGet, api) => ({
|
|
|
200
200
|
getListeners() {
|
|
201
201
|
return storeGet().listeners;
|
|
202
202
|
},
|
|
203
|
-
setListener({ formName, name, onChange, onReset, isTouched, isDirty, formItemId, internalErrors, onFocus, emitFocus, isInitied, type, onArrayChange }) {
|
|
203
|
+
setListener({ formName, name, onChange, onReset, isTouched, isDirty, formItemId, internalErrors, onFocus, emitFocus, isInitied, type, onArrayChange, hidden, collectOnHidden }) {
|
|
204
204
|
return storeSet(produce((state) => {
|
|
205
205
|
const storeListeners = state.listeners;
|
|
206
206
|
const findListenerIndex = state.listeners.findIndex((l) => l.formItemId === formItemId);
|
|
@@ -238,6 +238,12 @@ const createListenersSlice = (storeSet, storeGet, api) => ({
|
|
|
238
238
|
if (!isNil(onArrayChange)) {
|
|
239
239
|
storeListeners[findListenerIndex].onArrayChange = onArrayChange;
|
|
240
240
|
}
|
|
241
|
+
if (!isNil(hidden)) {
|
|
242
|
+
storeListeners[findListenerIndex].hidden = hidden;
|
|
243
|
+
}
|
|
244
|
+
if (!isNil(collectOnHidden)) {
|
|
245
|
+
storeListeners[findListenerIndex].collectOnHidden = collectOnHidden;
|
|
246
|
+
}
|
|
241
247
|
return;
|
|
242
248
|
}
|
|
243
249
|
storeListeners.push({
|
|
@@ -251,7 +257,11 @@ const createListenersSlice = (storeSet, storeGet, api) => ({
|
|
|
251
257
|
onReset,
|
|
252
258
|
isInitied: Boolean(isInitied),
|
|
253
259
|
type: type || "normal",
|
|
254
|
-
onArrayChange
|
|
260
|
+
onArrayChange,
|
|
261
|
+
onFocus,
|
|
262
|
+
emitFocus,
|
|
263
|
+
hidden: Boolean(hidden),
|
|
264
|
+
collectOnHidden
|
|
255
265
|
});
|
|
256
266
|
}));
|
|
257
267
|
},
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import FormList from "./components/Form/FormList";
|
|
|
7
7
|
import InputWrapper from "./components/Form/InputWrapper";
|
|
8
8
|
import Form, { useForm } from "./providers/Form";
|
|
9
9
|
import TestDialog from "./test/TestDialog";
|
|
10
|
+
import TestListener from "./test/TestListener";
|
|
10
11
|
|
|
11
12
|
import { Form as AntdForm } from "antd";
|
|
12
13
|
|
|
@@ -173,15 +174,16 @@ const App = () => {
|
|
|
173
174
|
exit={{ opacity: 0 }}
|
|
174
175
|
transition={{ duration: 1.5 }}
|
|
175
176
|
>
|
|
176
|
-
<
|
|
177
|
+
<Form.Item
|
|
177
178
|
valuePropName="checked"
|
|
178
179
|
getValueFromEvent={(_, checked) => checked}
|
|
179
180
|
name="checkControlledAfterInit"
|
|
180
181
|
controlAfterInit={true}
|
|
181
182
|
initialValue={true}
|
|
183
|
+
hidden
|
|
182
184
|
>
|
|
183
185
|
<Checkbox />
|
|
184
|
-
</
|
|
186
|
+
</Form.Item>
|
|
185
187
|
</motion.div>
|
|
186
188
|
<TestFormWatch />
|
|
187
189
|
<Button
|
|
@@ -202,6 +204,8 @@ const App = () => {
|
|
|
202
204
|
Reset
|
|
203
205
|
</Button>
|
|
204
206
|
</Form>
|
|
207
|
+
|
|
208
|
+
<TestListener />
|
|
205
209
|
</div>
|
|
206
210
|
);
|
|
207
211
|
};
|
|
@@ -15,6 +15,7 @@ export interface FormItemProps {
|
|
|
15
15
|
getValueFromEvent?: (...args: any[]) => any;
|
|
16
16
|
controlAfterInit?: boolean;
|
|
17
17
|
hidden?: boolean;
|
|
18
|
+
collectOnHidden?: boolean;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export default function FormItem({
|
|
@@ -28,6 +29,7 @@ export default function FormItem({
|
|
|
28
29
|
getValueFromEvent,
|
|
29
30
|
controlAfterInit = false,
|
|
30
31
|
hidden,
|
|
32
|
+
collectOnHidden,
|
|
31
33
|
}: FormItemProps) {
|
|
32
34
|
const elRef = useRef<any>(null);
|
|
33
35
|
|
|
@@ -49,6 +51,8 @@ export default function FormItem({
|
|
|
49
51
|
formItemId,
|
|
50
52
|
rules,
|
|
51
53
|
elementRef: elRef,
|
|
54
|
+
hidden,
|
|
55
|
+
collectOnHidden,
|
|
52
56
|
});
|
|
53
57
|
// console.log("re-render", formName, name);
|
|
54
58
|
|
|
@@ -37,6 +37,8 @@ interface UseFormItemControlProps {
|
|
|
37
37
|
formItemId?: string;
|
|
38
38
|
rules?: ValidationRule[];
|
|
39
39
|
elementRef?: RefObject<any> | null;
|
|
40
|
+
hidden?: boolean;
|
|
41
|
+
collectOnHidden?: boolean;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export interface UseFormItemControlReturn {
|
|
@@ -61,6 +63,8 @@ export default function useFormItemControl<T = any>({
|
|
|
61
63
|
formItemId,
|
|
62
64
|
rules,
|
|
63
65
|
elementRef,
|
|
66
|
+
hidden,
|
|
67
|
+
collectOnHidden,
|
|
64
68
|
}: UseFormItemControlProps): UseFormItemControlReturn {
|
|
65
69
|
const contextForm = useFormContext();
|
|
66
70
|
const {
|
|
@@ -216,9 +220,9 @@ export default function useFormItemControl<T = any>({
|
|
|
216
220
|
return rules || [];
|
|
217
221
|
}, [rules]);
|
|
218
222
|
|
|
219
|
-
useEffect(() => {
|
|
220
|
-
|
|
221
|
-
}, [value, listener]);
|
|
223
|
+
// useEffect(() => {
|
|
224
|
+
// console.log("Rules changed: ", { name, listener });
|
|
225
|
+
// }, [value, listener]);
|
|
222
226
|
|
|
223
227
|
const { data: errors, state } = useTaskEffect({
|
|
224
228
|
async task() {
|
|
@@ -569,11 +573,13 @@ export default function useFormItemControl<T = any>({
|
|
|
569
573
|
emitFocus,
|
|
570
574
|
isTouched: false,
|
|
571
575
|
isDirty: false,
|
|
572
|
-
isInitied:
|
|
576
|
+
isInitied: false,
|
|
573
577
|
name,
|
|
574
578
|
formName: formName || form?.formName || contextForm?.formName,
|
|
575
579
|
formItemId,
|
|
576
580
|
onReset,
|
|
581
|
+
hidden,
|
|
582
|
+
collectOnHidden,
|
|
577
583
|
});
|
|
578
584
|
}
|
|
579
585
|
|
|
@@ -592,6 +598,16 @@ export default function useFormItemControl<T = any>({
|
|
|
592
598
|
// };
|
|
593
599
|
}, []);
|
|
594
600
|
|
|
601
|
+
// useEffect(() => {
|
|
602
|
+
// if (listener) {
|
|
603
|
+
// setListener({
|
|
604
|
+
// formItemId,
|
|
605
|
+
// hidden,
|
|
606
|
+
// collectOnHidden,
|
|
607
|
+
// });
|
|
608
|
+
// }
|
|
609
|
+
// }, [hidden, collectOnHidden]);
|
|
610
|
+
|
|
595
611
|
useEffect(() => {
|
|
596
612
|
if (listener) {
|
|
597
613
|
setListener({
|
|
@@ -337,7 +337,12 @@ export default function useFormListControl<T = any>({
|
|
|
337
337
|
name,
|
|
338
338
|
listFormInitValues,
|
|
339
339
|
);
|
|
340
|
-
|
|
340
|
+
if (getListener(formItemId)) {
|
|
341
|
+
setListener({
|
|
342
|
+
formItemId,
|
|
343
|
+
isInitied: true,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
341
346
|
return;
|
|
342
347
|
}
|
|
343
348
|
|
|
@@ -355,7 +360,12 @@ export default function useFormListControl<T = any>({
|
|
|
355
360
|
|
|
356
361
|
setListFields(result);
|
|
357
362
|
setListFormInitValues(internalInitValue as any);
|
|
358
|
-
|
|
363
|
+
if (getListener(formItemId)) {
|
|
364
|
+
setListener({
|
|
365
|
+
formItemId,
|
|
366
|
+
isInitied: true,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
359
369
|
return;
|
|
360
370
|
}
|
|
361
371
|
|
|
@@ -383,7 +393,12 @@ export default function useFormListControl<T = any>({
|
|
|
383
393
|
|
|
384
394
|
setListFields(result);
|
|
385
395
|
setListFormInitValues(initialValues as any);
|
|
386
|
-
|
|
396
|
+
if (getListener(formItemId)) {
|
|
397
|
+
setListener({
|
|
398
|
+
formItemId,
|
|
399
|
+
isInitied: true,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
387
402
|
// console.log("Get form init values: ", internalInitValue, result);
|
|
388
403
|
|
|
389
404
|
return;
|
package/src/providers/Form.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cloneDeep,
|
|
3
|
+
filter,
|
|
3
4
|
get,
|
|
4
5
|
isEqual,
|
|
5
6
|
isNil,
|
|
@@ -14,8 +15,9 @@ import { createContext, useContext, useEffect, useState } from "react";
|
|
|
14
15
|
import { flushSync } from "react-dom";
|
|
15
16
|
import { useShallow } from "zustand/react/shallow"; // Import useShallow
|
|
16
17
|
import FormCleanUp from "../components/Form/FormCleanUp";
|
|
18
|
+
import FormItem from "../components/Form/FormItem";
|
|
17
19
|
import { SUBMIT_STATE } from "../constants/form";
|
|
18
|
-
import { ListenerItem, useFormStore } from "../stores/formStore";
|
|
20
|
+
import { ListenerItem, SubmitProps, useFormStore } from "../stores/formStore";
|
|
19
21
|
import type {
|
|
20
22
|
PublicFormInstance,
|
|
21
23
|
UseFormItemStateWatchReturn,
|
|
@@ -34,6 +36,7 @@ export interface FormProps<T = any> extends Omit<
|
|
|
34
36
|
FormHTMLAttributes<HTMLFormElement>,
|
|
35
37
|
"onSubmit"
|
|
36
38
|
> {
|
|
39
|
+
collectHiddenFields?: boolean;
|
|
37
40
|
children: ReactNode;
|
|
38
41
|
formName: string;
|
|
39
42
|
initialValues?: T;
|
|
@@ -55,6 +58,7 @@ export default function Form<T = any>({
|
|
|
55
58
|
onReject,
|
|
56
59
|
onFinally,
|
|
57
60
|
FormElement,
|
|
61
|
+
collectHiddenFields: formCollectHiddenFields = true,
|
|
58
62
|
...props
|
|
59
63
|
}: FormProps<T>) {
|
|
60
64
|
const {
|
|
@@ -236,16 +240,36 @@ export default function Form<T = any>({
|
|
|
236
240
|
state: _,
|
|
237
241
|
reset,
|
|
238
242
|
} = useTask({
|
|
239
|
-
async task(props) {
|
|
243
|
+
async task(props?: SubmitProps<T>) {
|
|
240
244
|
try {
|
|
241
245
|
flushSync(setFormState({ formName, submitState: "submitting" }));
|
|
242
246
|
const errorFields = getAllFieldErrors();
|
|
243
|
-
const listeners = getListeners().filter(
|
|
247
|
+
const listeners: ListenerItem[] = getListeners().filter(
|
|
248
|
+
(l) => l.formName === formName,
|
|
249
|
+
);
|
|
244
250
|
const formValues = getFormValues(formName);
|
|
245
251
|
|
|
246
252
|
const resultValues = cloneDeep(formValues);
|
|
247
253
|
const cleanValues = {} as T;
|
|
248
|
-
uniqBy(
|
|
254
|
+
uniqBy(
|
|
255
|
+
filter(listeners, (l: ListenerItem) => {
|
|
256
|
+
// console.log("Check collect field hidden: ", {
|
|
257
|
+
// name: l.name,
|
|
258
|
+
// hidden: l.hidden,
|
|
259
|
+
// collectOnHidden: l.collectOnHidden,
|
|
260
|
+
// collectHiddenFields,
|
|
261
|
+
// });
|
|
262
|
+
if (!l.hidden) return true;
|
|
263
|
+
if (isNil(props?.collectHiddenFields)) {
|
|
264
|
+
if (isNil(l.collectOnHidden)) {
|
|
265
|
+
return formCollectHiddenFields;
|
|
266
|
+
}
|
|
267
|
+
return Boolean(l.collectOnHidden);
|
|
268
|
+
}
|
|
269
|
+
return props.collectHiddenFields;
|
|
270
|
+
}),
|
|
271
|
+
(l) => l.name,
|
|
272
|
+
).forEach((l) => {
|
|
249
273
|
set(cleanValues as any, l.name, get(resultValues, l.name));
|
|
250
274
|
});
|
|
251
275
|
|
|
@@ -581,6 +605,7 @@ export const useFormItemStateWatch = <T = any,>(
|
|
|
581
605
|
};
|
|
582
606
|
|
|
583
607
|
Form.useForm = useForm;
|
|
608
|
+
Form.Item = FormItem;
|
|
584
609
|
Form.useWatch = useWatch;
|
|
585
610
|
Form.useSubmitDataWatch = useSubmitDataWatch;
|
|
586
611
|
Form.useFormStateWatch = useFormStateWatch;
|
package/src/stores/formStore.ts
CHANGED
|
@@ -4,10 +4,25 @@ import { v4 } from "uuid";
|
|
|
4
4
|
import { create } from "zustand";
|
|
5
5
|
import { getAllNoneObjStringPath } from "../utils/obj.util";
|
|
6
6
|
type ListenerFormItemType = "normal" | "array";
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
export interface SubmitProps<T = any> {
|
|
9
|
+
externalFinishCallback?: (values: T, allValues?: any) => void | Promise<void>;
|
|
10
|
+
externalRejectCallback?: (errorFields: any[]) => void | Promise<void>;
|
|
11
|
+
externalFinallyCallback?: (result: {
|
|
12
|
+
errorsField: any[];
|
|
13
|
+
values: T;
|
|
14
|
+
withUnRegisteredValues: any;
|
|
15
|
+
}) => void | Promise<void>;
|
|
16
|
+
callBothFinish?: boolean;
|
|
17
|
+
callBothReject?: boolean;
|
|
18
|
+
callBothFinally?: boolean;
|
|
19
|
+
collectHiddenFields?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface FormInstance<T = any> {
|
|
8
23
|
formName: string;
|
|
9
24
|
resetFields: (values?: any) => void;
|
|
10
|
-
submit: (
|
|
25
|
+
submit: (props?: SubmitProps<T>) => void;
|
|
11
26
|
submitAsync: (values?: any) => Promise<any>;
|
|
12
27
|
setFieldValue: (name: string, value: any, options?: any) => void;
|
|
13
28
|
setFieldValues: (values: Record<string, any>, options?: any) => void;
|
|
@@ -31,6 +46,8 @@ export interface ListenerItem {
|
|
|
31
46
|
emitFocus?: any;
|
|
32
47
|
isInitied?: boolean;
|
|
33
48
|
type?: ListenerFormItemType;
|
|
49
|
+
hidden?: boolean;
|
|
50
|
+
collectOnHidden?: boolean;
|
|
34
51
|
}
|
|
35
52
|
|
|
36
53
|
export interface CleanUpItem {
|
|
@@ -362,7 +379,7 @@ const createFormStoreSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
|
362
379
|
|
|
363
380
|
// Listeners Slice
|
|
364
381
|
const createListenersSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
365
|
-
listeners: [],
|
|
382
|
+
listeners: [] as ListenerItem[],
|
|
366
383
|
getListener(formItemId) {
|
|
367
384
|
return storeGet().listeners.find((l) => l.formItemId === formItemId);
|
|
368
385
|
},
|
|
@@ -383,6 +400,8 @@ const createListenersSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
|
383
400
|
isInitied,
|
|
384
401
|
type,
|
|
385
402
|
onArrayChange,
|
|
403
|
+
hidden,
|
|
404
|
+
collectOnHidden,
|
|
386
405
|
}: Partial<ListenerItem> & { formItemId: string }) {
|
|
387
406
|
return storeSet(
|
|
388
407
|
produce<any>((state: any) => {
|
|
@@ -428,6 +447,14 @@ const createListenersSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
|
428
447
|
storeListeners[findListenerIndex].onArrayChange = onArrayChange;
|
|
429
448
|
}
|
|
430
449
|
|
|
450
|
+
if (!isNil(hidden)) {
|
|
451
|
+
storeListeners[findListenerIndex].hidden = hidden;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (!isNil(collectOnHidden)) {
|
|
455
|
+
storeListeners[findListenerIndex].collectOnHidden = collectOnHidden;
|
|
456
|
+
}
|
|
457
|
+
|
|
431
458
|
return;
|
|
432
459
|
}
|
|
433
460
|
storeListeners.push({
|
|
@@ -442,6 +469,10 @@ const createListenersSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
|
442
469
|
isInitied: Boolean(isInitied),
|
|
443
470
|
type: type || "normal",
|
|
444
471
|
onArrayChange,
|
|
472
|
+
onFocus,
|
|
473
|
+
emitFocus,
|
|
474
|
+
hidden: Boolean(hidden),
|
|
475
|
+
collectOnHidden,
|
|
445
476
|
});
|
|
446
477
|
}),
|
|
447
478
|
);
|