react-form-manage 1.0.8-beta.22 → 1.0.8-beta.24
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 +17 -0
- package/dist/components/Form/FormItem.d.ts +10 -4
- package/dist/components/Form/FormItem.js +52 -14
- package/dist/hooks/useFormItemControl.d.ts +3 -1
- package/dist/hooks/useFormItemControl.js +29 -15
- package/dist/hooks/useFormListControl.js +18 -0
- package/dist/providers/Form.d.ts +4 -1
- package/dist/providers/Form.js +17 -5
- package/dist/stores/formStore.d.ts +17 -2
- package/dist/stores/formStore.js +12 -2
- package/dist/test/CommonTest.d.ts +3 -0
- package/dist/test/CommonTest.js +49 -0
- package/dist/test/TestWrapperFormItem.d.ts +3 -0
- package/dist/test/TestWrapperFormItem.js +13 -0
- package/package.json +1 -1
- package/src/App.tsx +11 -176
- package/src/components/Form/FormCleanUp.tsx +1 -1
- package/src/components/Form/FormItem.tsx +174 -56
- package/src/hooks/useFormItemControl.ts +35 -12
- package/src/hooks/useFormListControl.ts +18 -3
- package/src/providers/Form.tsx +31 -5
- package/src/stores/formStore.ts +34 -3
- package/src/test/CommonTest.tsx +177 -0
- package/src/test/TestWrapperFormItem.tsx +34 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.0.8-beta.24] - 2026-02-04
|
|
6
|
+
|
|
7
|
+
### Fixes
|
|
8
|
+
- Fix cleanup item execution for proper FormItem unmounting
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
- Add `Component` prop to FormItem for wrapping input with custom elements
|
|
12
|
+
- Support custom wrapper components in FormItem
|
|
13
|
+
|
|
14
|
+
## [1.0.8-beta.23] - 2026-02-04
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
- Add `hidden` prop to FormItem for conditional visibility control
|
|
18
|
+
- Add `collectHiddenValue` option to control whether hidden form items contribute to form data collection
|
|
19
|
+
- FormItem can now be retrieved from Form instance
|
|
20
|
+
- Enhanced form item state management with visibility tracking
|
|
21
|
+
|
|
5
22
|
## [1.0.8-beta.22] - 2026-02-02
|
|
6
23
|
|
|
7
24
|
### Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ReactElement } from "react";
|
|
1
|
+
import type { ComponentProps, FC, ReactElement } from "react";
|
|
2
2
|
import type { ValidationRule } from "../../types/public";
|
|
3
|
-
export
|
|
3
|
+
export type BaseFormItemProps = {
|
|
4
4
|
children: ReactElement<any>;
|
|
5
5
|
name: string;
|
|
6
6
|
formName?: string;
|
|
@@ -11,5 +11,11 @@ export interface FormItemProps {
|
|
|
11
11
|
getValueFromEvent?: (...args: any[]) => any;
|
|
12
12
|
controlAfterInit?: boolean;
|
|
13
13
|
hidden?: boolean;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
collectOnHidden?: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type FormItemProps<TCustomWrapper extends FC<any> | undefined> = BaseFormItemProps & ({
|
|
17
|
+
Component?: undefined;
|
|
18
|
+
} | ({
|
|
19
|
+
Component: TCustomWrapper;
|
|
20
|
+
} & Omit<ComponentProps<TCustomWrapper>, keyof BaseFormItemProps>));
|
|
21
|
+
export default function FormItem<TCustomWrapper extends FC<any> | undefined>({ children, Component, name, formName, initialValue, formItemId: externalFormItemId, rules, valuePropName, getValueFromEvent, controlAfterInit, hidden, collectOnHidden, ...props }: FormItemProps<TCustomWrapper>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,21 +1,45 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { isNil } from "lodash";
|
|
3
|
+
import { cloneElement, Fragment, useEffect, useRef, useState } from "react";
|
|
3
4
|
import { v4 } from "uuid";
|
|
4
5
|
import useFormItemControl from "../../hooks/useFormItemControl";
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
formName,
|
|
6
|
+
function BaseFormItem({ children, name, elementRef: elRef, valuePropName, getValueFromEvent, onChange, value, isDirty, errors, onFocus, state, submitState, isTouched }) {
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
}, [value]);
|
|
9
|
+
return cloneElement(children, {
|
|
10
10
|
name,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
ref: elRef,
|
|
12
|
+
[valuePropName]: value,
|
|
13
|
+
onChange: (...args) => {
|
|
14
|
+
let val = args[0];
|
|
15
|
+
if (getValueFromEvent && typeof getValueFromEvent === "function") {
|
|
16
|
+
val = getValueFromEvent(...args);
|
|
17
|
+
} else {
|
|
18
|
+
const e = args[0];
|
|
19
|
+
if (e && e.target) {
|
|
20
|
+
val = e.target.value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
onChange(val);
|
|
24
|
+
},
|
|
25
|
+
// onFocus: () => {
|
|
26
|
+
// setIsTouched(true);
|
|
27
|
+
// },
|
|
28
|
+
// isTouched: isTouched,
|
|
29
|
+
isDirty,
|
|
30
|
+
// errors: errors,
|
|
31
|
+
// formState,
|
|
32
|
+
errors,
|
|
33
|
+
onFocus,
|
|
34
|
+
validateState: state,
|
|
35
|
+
submitState,
|
|
36
|
+
isTouched
|
|
15
37
|
});
|
|
16
|
-
|
|
38
|
+
}
|
|
39
|
+
function FormItemWithWrapper({ children, name, elementRef: elRef, valuePropName, getValueFromEvent, onChange, value, isDirty, errors, onFocus, state, submitState, isTouched, Component, ...props }) {
|
|
40
|
+
return _jsx(Component, { ...props, children: cloneElement(children, {
|
|
17
41
|
name,
|
|
18
|
-
|
|
42
|
+
ref: elRef,
|
|
19
43
|
[valuePropName]: value,
|
|
20
44
|
onChange: (...args) => {
|
|
21
45
|
let val = args[0];
|
|
@@ -39,10 +63,24 @@ function FormItem({ children, name, formName, initialValue, formItemId: external
|
|
|
39
63
|
errors,
|
|
40
64
|
onFocus,
|
|
41
65
|
validateState: state,
|
|
42
|
-
ref: elRef,
|
|
43
66
|
submitState,
|
|
44
67
|
isTouched
|
|
45
|
-
})
|
|
68
|
+
}) });
|
|
69
|
+
}
|
|
70
|
+
function FormItem({ children, Component, name, formName, initialValue, formItemId: externalFormItemId, rules, valuePropName = "value", getValueFromEvent, controlAfterInit = false, hidden, collectOnHidden, ...props }) {
|
|
71
|
+
const [formItemId] = useState(externalFormItemId != null ? externalFormItemId : v4());
|
|
72
|
+
const elRef = useRef(null);
|
|
73
|
+
const { value, onChange, errors, state, onFocus, isDirty, submitState, isTouched, isInitied } = useFormItemControl({
|
|
74
|
+
formName,
|
|
75
|
+
name,
|
|
76
|
+
initialValue,
|
|
77
|
+
formItemId,
|
|
78
|
+
rules,
|
|
79
|
+
elementRef: elRef,
|
|
80
|
+
hidden,
|
|
81
|
+
collectOnHidden
|
|
82
|
+
});
|
|
83
|
+
return _jsx(Fragment, { children: !hidden && children ? isNil(Component) ? _jsx(BaseFormItem, { elementRef: elRef, name, valuePropName, getValueFromEvent, value, onChange, errors, state, onFocus, isDirty, submitState, isTouched, formItemId, children }) : _jsx(FormItemWithWrapper, { elementRef: elRef, name, valuePropName, getValueFromEvent, value, onChange, errors, state, onFocus, isDirty, submitState, isTouched, formItemId, Component, ...props, children }) : null }, `control-after-init-${Boolean(controlAfterInit && isInitied) ? "1" : "0"}-${externalFormItemId}`);
|
|
46
84
|
}
|
|
47
85
|
export {
|
|
48
86
|
FormItem as default
|
|
@@ -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 {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { get, has, isNil } from "lodash";
|
|
2
2
|
import { useTaskEffect } from "minh-custom-hooks-release";
|
|
3
|
-
import { useEffect, useMemo } from "react";
|
|
3
|
+
import { useEffect, useLayoutEffect, useMemo } from "react";
|
|
4
4
|
import { useShallow } from "zustand/react/shallow";
|
|
5
5
|
import { IS_ALPHABET_STRING_AND_NUMBER_REGEX, IS_EMAIL_REGEX, IS_NAME_REGEX, IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_REGEX, IS_NO_SPACE_ALPHABET_STRING_REGEX, IS_NOSPACE_STRING_AND_NUMBER_REGEX, IS_PASSWORD_REGEX, IS_POSITIVE_INTEGER_STRING_NUMBER_REGEX, IS_POSITIVE_STRING_NUMBER_REGEX, IS_STRING_AND_NUMBER_REGEX, IS_STRING_NUMBER_REGEX, IS_USERNAME_REGEX, IS_VIETNAMESE_PHONE_NUMBER_REGEX } from "../constants/validation";
|
|
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,
|
|
@@ -15,7 +15,10 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
15
15
|
getFormValues,
|
|
16
16
|
// getFormState,
|
|
17
17
|
isStateInitied,
|
|
18
|
-
submitState
|
|
18
|
+
submitState,
|
|
19
|
+
getListener,
|
|
20
|
+
revokeListener,
|
|
21
|
+
clearObjKeyItem
|
|
19
22
|
} = useFormStore(useShallow((state2) => {
|
|
20
23
|
var _a, _b, _c, _d;
|
|
21
24
|
return {
|
|
@@ -25,7 +28,10 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
25
28
|
getFormValues: state2.getFormValues,
|
|
26
29
|
// getFormState: state.getFormState,
|
|
27
30
|
isStateInitied: (_b = (_a = state2.formStates) == null ? void 0 : _a[formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName)]) == null ? void 0 : _b.isInitied,
|
|
28
|
-
submitState: (_d = (_c = state2.formStates) == null ? void 0 : _c[formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName)]) == null ? void 0 : _d.submitState
|
|
31
|
+
submitState: (_d = (_c = state2.formStates) == null ? void 0 : _c[formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName)]) == null ? void 0 : _d.submitState,
|
|
32
|
+
getListener: state2.getListener,
|
|
33
|
+
revokeListener: state2.revokeListener,
|
|
34
|
+
clearObjKeyItem: state2.clearObjKeyItem
|
|
29
35
|
};
|
|
30
36
|
}));
|
|
31
37
|
const { setCleanUpStack } = useFormStore(useShallow((state2) => ({
|
|
@@ -88,8 +94,6 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
88
94
|
const internalRules = useMemo(() => {
|
|
89
95
|
return rules || [];
|
|
90
96
|
}, [rules]);
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
}, [value, listener]);
|
|
93
97
|
const { data: errors, state } = useTaskEffect({
|
|
94
98
|
async task() {
|
|
95
99
|
const listErrors = [];
|
|
@@ -297,29 +301,39 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
297
301
|
return;
|
|
298
302
|
}
|
|
299
303
|
}, [isStateInitied]);
|
|
300
|
-
|
|
304
|
+
useLayoutEffect(() => {
|
|
301
305
|
if (!listener) {
|
|
302
306
|
setListener({
|
|
303
307
|
onChange,
|
|
304
308
|
emitFocus,
|
|
305
309
|
isTouched: false,
|
|
306
310
|
isDirty: false,
|
|
307
|
-
isInitied:
|
|
311
|
+
isInitied: false,
|
|
308
312
|
name,
|
|
309
313
|
formName: formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName),
|
|
310
314
|
formItemId,
|
|
311
|
-
onReset
|
|
315
|
+
onReset,
|
|
316
|
+
hidden,
|
|
317
|
+
collectOnHidden
|
|
312
318
|
});
|
|
313
319
|
}
|
|
314
320
|
return () => {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
+
revokeListener(formItemId, (listener2, same) => {
|
|
322
|
+
if (!same.length) {
|
|
323
|
+
clearObjKeyItem(listener2.formName, listener2.name);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
321
326
|
};
|
|
322
327
|
}, []);
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
if (listener) {
|
|
330
|
+
setListener({
|
|
331
|
+
formItemId,
|
|
332
|
+
hidden,
|
|
333
|
+
collectOnHidden
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}, [hidden, collectOnHidden]);
|
|
323
337
|
useEffect(() => {
|
|
324
338
|
if (listener) {
|
|
325
339
|
setListener({
|
|
@@ -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 () => {
|
|
@@ -291,7 +302,7 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
291
302
|
}, []);
|
|
292
303
|
return _jsxs(FormContext.Provider, { value: {
|
|
293
304
|
formName
|
|
294
|
-
}, children: [FormElement ? _jsx(FormElement, { onSubmit: (e) => {
|
|
305
|
+
}, children: [_jsx(FormCleanUp, {}), FormElement ? _jsx(FormElement, { onSubmit: (e) => {
|
|
295
306
|
e.preventDefault();
|
|
296
307
|
e.stopPropagation();
|
|
297
308
|
runSubmit(void 0);
|
|
@@ -299,7 +310,7 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
299
310
|
e.preventDefault();
|
|
300
311
|
e.stopPropagation();
|
|
301
312
|
runSubmit(void 0);
|
|
302
|
-
}, ...props, children })
|
|
313
|
+
}, ...props, children })] });
|
|
303
314
|
}
|
|
304
315
|
function useFormContext() {
|
|
305
316
|
const c = useContext(FormContext);
|
|
@@ -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
|
},
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Checkbox, Input } from "antd";
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
import FormItem from "../components/Form/FormItem";
|
|
5
|
+
import FormList from "../components/Form/FormList";
|
|
6
|
+
import InputWrapper from "../components/Form/InputWrapper";
|
|
7
|
+
import Form from "../providers/Form";
|
|
8
|
+
function CommonTest({}) {
|
|
9
|
+
const [form] = Form.useForm("form1");
|
|
10
|
+
const watchCheckBox = Form.useWatch("checkControlledAfterInit", "form1");
|
|
11
|
+
return _jsxs(Form, { initialValues: {
|
|
12
|
+
TestData: "",
|
|
13
|
+
numericCode: ""
|
|
14
|
+
// arr: [{ el: "Item 1" }, { el: "Item 2" }],
|
|
15
|
+
}, onFinish: (values) => {
|
|
16
|
+
}, formName: "form1", children: [_jsx(FormItem, { name: "username", rules: [
|
|
17
|
+
{
|
|
18
|
+
required: true,
|
|
19
|
+
message: "Test"
|
|
20
|
+
}
|
|
21
|
+
], initialValue: "283746", children: _jsx(InputWrapper, { children: _jsx(Input, {}) }) }), _jsx(FormItem, { name: "numericCode", rules: [
|
|
22
|
+
{ required: true, message: "Vui l\xF2ng nh\u1EADp m\xE3" },
|
|
23
|
+
{
|
|
24
|
+
pattern: /^\d+$/,
|
|
25
|
+
message: "Ch\u1EC9 cho ph\xE9p chu\u1ED7i s\u1ED1"
|
|
26
|
+
}
|
|
27
|
+
], children: _jsx(InputWrapper, { children: _jsx(Input, { placeholder: "M\xE3 ch\u1EC9 g\u1ED3m s\u1ED1", style: { width: 200 } }) }) }), _jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 1 }, children: _jsx(FormItem, { name: "motionTest", controlAfterInit: true, initialValue: "1234134", children: _jsx(InputWrapper, { children: _jsx(Input, { placeholder: "Motion Test", style: { width: 200 } }) }) }) }), _jsx(FormList, { initialValues: [
|
|
28
|
+
{
|
|
29
|
+
el: "sdfsdf",
|
|
30
|
+
d: { child: "Test Child" }
|
|
31
|
+
}
|
|
32
|
+
], name: "arr", children: (fields, { add, remove, move }) => _jsxs("div", { children: [fields.map((field, index) => _jsxs("div", { style: { marginBottom: 8 }, children: [_jsx(FormItem, { name: `${field.name}.el`, initialValue: "Ch\xE9m gi\xF3", children: _jsx(InputWrapper, { children: _jsx(Input, { placeholder: "Item value", style: { width: 200 } }) }) }), _jsx(FormItem, { name: `${field.name}.d.child`, initialValue: "Con c\u1EE7a item", children: _jsx(InputWrapper, { children: _jsx(Input, { placeholder: "Item value", style: { width: 200 } }) }) }), _jsx(Button, { onClick: () => remove({ index }), style: { marginLeft: 8 }, children: "Remove" }), index > 0 && _jsx(Button, { onClick: () => move({ from: index, to: index - 1 }), style: { marginLeft: 8 }, children: "Move Up" }), index < fields.length - 1 && _jsx(Button, { onClick: () => move({ from: index, to: index + 1 }), style: { marginLeft: 8 }, children: "Move Down" })] }, field.key)), _jsx(Button, { onClick: () => add(fields.length), children: "Add Item" })] }) }), _jsx(Button, { onClick: () => {
|
|
33
|
+
form == null ? void 0 : form.setFieldValue("arr", [
|
|
34
|
+
{ el: "Set Item 1" },
|
|
35
|
+
{ el: "Set Item 2" },
|
|
36
|
+
{ el: "Set Item 3" }
|
|
37
|
+
]);
|
|
38
|
+
}, children: "Test set array list value" }), _jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 1.5 }, children: _jsx(Form.Item, { valuePropName: "checked", getValueFromEvent: (_, checked) => checked, name: "checkControlledAfterInit", controlAfterInit: true, initialValue: true, hidden: true, children: _jsx(Checkbox, {}) }) }), _jsx(Button, { onClick: () => {
|
|
39
|
+
const current = form == null ? void 0 : form.getFieldValue("checkControlledAfterInit");
|
|
40
|
+
form == null ? void 0 : form.setFieldValue("checkControlledAfterInit", !current);
|
|
41
|
+
}, children: "Toggle" }), _jsx(Button, { htmlType: "submit", children: "Submit" }), _jsx(Button, { onClick: () => {
|
|
42
|
+
var _a;
|
|
43
|
+
(_a = form == null ? void 0 : form.resetFields) == null ? void 0 : _a.call(form);
|
|
44
|
+
}, children: "Reset" })] });
|
|
45
|
+
}
|
|
46
|
+
var stdin_default = CommonTest;
|
|
47
|
+
export {
|
|
48
|
+
stdin_default as default
|
|
49
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Col, Input, Row } from "antd";
|
|
3
|
+
import { useToggle } from "minh-custom-hooks-release";
|
|
4
|
+
import Form from "../providers/Form";
|
|
5
|
+
function TestWrapperFormItem({}) {
|
|
6
|
+
const { state, toggle } = useToggle(false);
|
|
7
|
+
return _jsxs(Form, { onFinish: (values, all) => {
|
|
8
|
+
}, formName: "testWrapper", children: [_jsx(Row, { children: _jsx(Form.Item, { hidden: !state, name: "test", collectOnHidden: false, initialValue: "test", Component: Col, xs: 12, children: _jsx(Input, {}) }) }), _jsx(Button, { htmlType: "submit", children: "Submit" }), _jsx(Button, { onClick: toggle, children: state ? "Off" : "On" })] });
|
|
9
|
+
}
|
|
10
|
+
var stdin_default = TestWrapperFormItem;
|
|
11
|
+
export {
|
|
12
|
+
stdin_default as default
|
|
13
|
+
};
|