react-form-manage 1.0.8-beta.23 → 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 +9 -0
- package/dist/components/Form/FormItem.d.ts +9 -4
- package/dist/components/Form/FormItem.js +52 -16
- package/dist/hooks/useFormItemControl.js +24 -10
- package/dist/providers/Form.js +2 -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 +9 -178
- package/src/components/Form/FormCleanUp.tsx +1 -1
- package/src/components/Form/FormItem.tsx +170 -56
- package/src/hooks/useFormItemControl.ts +24 -17
- package/src/providers/Form.tsx +2 -1
- package/src/test/CommonTest.tsx +177 -0
- package/src/test/TestWrapperFormItem.tsx +34 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
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
|
+
|
|
5
14
|
## [1.0.8-beta.23] - 2026-02-04
|
|
6
15
|
|
|
7
16
|
### Features
|
|
@@ -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;
|
|
@@ -12,5 +12,10 @@ export interface FormItemProps {
|
|
|
12
12
|
controlAfterInit?: boolean;
|
|
13
13
|
hidden?: boolean;
|
|
14
14
|
collectOnHidden?: boolean;
|
|
15
|
-
}
|
|
16
|
-
export
|
|
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,23 +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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
17
37
|
});
|
|
18
|
-
|
|
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, {
|
|
19
41
|
name,
|
|
20
|
-
|
|
42
|
+
ref: elRef,
|
|
21
43
|
[valuePropName]: value,
|
|
22
44
|
onChange: (...args) => {
|
|
23
45
|
let val = args[0];
|
|
@@ -41,10 +63,24 @@ function FormItem({ children, name, formName, initialValue, formItemId: external
|
|
|
41
63
|
errors,
|
|
42
64
|
onFocus,
|
|
43
65
|
validateState: state,
|
|
44
|
-
ref: elRef,
|
|
45
66
|
submitState,
|
|
46
67
|
isTouched
|
|
47
|
-
})
|
|
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}`);
|
|
48
84
|
}
|
|
49
85
|
export {
|
|
50
86
|
FormItem as default
|
|
@@ -1,6 +1,6 @@
|
|
|
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";
|
|
@@ -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) => ({
|
|
@@ -295,7 +301,7 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
295
301
|
return;
|
|
296
302
|
}
|
|
297
303
|
}, [isStateInitied]);
|
|
298
|
-
|
|
304
|
+
useLayoutEffect(() => {
|
|
299
305
|
if (!listener) {
|
|
300
306
|
setListener({
|
|
301
307
|
onChange,
|
|
@@ -312,14 +318,22 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
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({
|
package/dist/providers/Form.js
CHANGED
|
@@ -302,7 +302,7 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
302
302
|
}, []);
|
|
303
303
|
return _jsxs(FormContext.Provider, { value: {
|
|
304
304
|
formName
|
|
305
|
-
}, children: [FormElement ? _jsx(FormElement, { onSubmit: (e) => {
|
|
305
|
+
}, children: [_jsx(FormCleanUp, {}), FormElement ? _jsx(FormElement, { onSubmit: (e) => {
|
|
306
306
|
e.preventDefault();
|
|
307
307
|
e.stopPropagation();
|
|
308
308
|
runSubmit(void 0);
|
|
@@ -310,7 +310,7 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
310
310
|
e.preventDefault();
|
|
311
311
|
e.stopPropagation();
|
|
312
312
|
runSubmit(void 0);
|
|
313
|
-
}, ...props, children })
|
|
313
|
+
}, ...props, children })] });
|
|
314
314
|
}
|
|
315
315
|
function useFormContext() {
|
|
316
316
|
const c = useContext(FormContext);
|
|
@@ -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
|
+
};
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Button, Input } from "antd";
|
|
1
|
+
import { Input } from "antd";
|
|
3
2
|
import { motion } from "framer-motion";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import FormList from "./components/Form/FormList";
|
|
7
|
-
import InputWrapper from "./components/Form/InputWrapper";
|
|
8
|
-
import Form, { useForm } from "./providers/Form";
|
|
9
|
-
import TestDialog from "./test/TestDialog";
|
|
3
|
+
import Form from "./providers/Form";
|
|
4
|
+
import CommonTest from "./test/CommonTest";
|
|
10
5
|
import TestListener from "./test/TestListener";
|
|
6
|
+
import TestWrapperFormItem from "./test/TestWrapperFormItem";
|
|
11
7
|
|
|
12
8
|
import { Form as AntdForm } from "antd";
|
|
13
9
|
|
|
@@ -18,17 +14,6 @@ function TestFormWatch() {
|
|
|
18
14
|
}
|
|
19
15
|
|
|
20
16
|
const App = () => {
|
|
21
|
-
const [form] = useForm("form1");
|
|
22
|
-
|
|
23
|
-
const watchCheckBox = Form.useWatch("checkControlledAfterInit", "form1");
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
if (form) {
|
|
27
|
-
// setTimeout(() => {
|
|
28
|
-
// form.setFieldValue("TestData", "HelloWorld");
|
|
29
|
-
// }, 500);
|
|
30
|
-
}
|
|
31
|
-
}, [form]);
|
|
32
17
|
return (
|
|
33
18
|
<div>
|
|
34
19
|
<AntdForm>
|
|
@@ -45,167 +30,13 @@ const App = () => {
|
|
|
45
30
|
</AntdForm>
|
|
46
31
|
|
|
47
32
|
{/* Hidden Test */}
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// arr: [{ el: "Item 1" }, { el: "Item 2" }],
|
|
53
|
-
}}
|
|
54
|
-
onFinish={(values) => {
|
|
55
|
-
console.log(values);
|
|
56
|
-
}}
|
|
57
|
-
formName={"form1"}
|
|
58
|
-
// hidden
|
|
59
|
-
>
|
|
60
|
-
<FormItem
|
|
61
|
-
name={"username"}
|
|
62
|
-
rules={[
|
|
63
|
-
{
|
|
64
|
-
required: true,
|
|
65
|
-
message: "Test",
|
|
66
|
-
},
|
|
67
|
-
]}
|
|
68
|
-
initialValue={"283746"}
|
|
69
|
-
// hidden
|
|
70
|
-
>
|
|
71
|
-
<InputWrapper>
|
|
72
|
-
<Input />
|
|
73
|
-
</InputWrapper>
|
|
74
|
-
</FormItem>
|
|
75
|
-
|
|
76
|
-
{/* Numberic test */}
|
|
77
|
-
<FormItem
|
|
78
|
-
name={"numericCode"}
|
|
79
|
-
rules={[
|
|
80
|
-
{ required: true, message: "Vui lòng nhập mã" },
|
|
81
|
-
{
|
|
82
|
-
pattern: /^\d+$/,
|
|
83
|
-
message: "Chỉ cho phép chuỗi số",
|
|
84
|
-
},
|
|
85
|
-
]}
|
|
86
|
-
>
|
|
87
|
-
<InputWrapper>
|
|
88
|
-
<Input placeholder="Mã chỉ gồm số" style={{ width: 200 }} />
|
|
89
|
-
</InputWrapper>
|
|
90
|
-
</FormItem>
|
|
91
|
-
|
|
92
|
-
{/* Motion Test */}
|
|
93
|
-
<motion.div
|
|
94
|
-
initial={{ opacity: 0 }}
|
|
95
|
-
animate={{ opacity: 1 }}
|
|
96
|
-
exit={{ opacity: 0 }}
|
|
97
|
-
transition={{ duration: 1 }}
|
|
98
|
-
>
|
|
99
|
-
<FormItem name="motionTest" controlAfterInit initialValue={"1234134"}>
|
|
100
|
-
<InputWrapper>
|
|
101
|
-
<Input placeholder="Motion Test" style={{ width: 200 }} />
|
|
102
|
-
</InputWrapper>
|
|
103
|
-
</FormItem>
|
|
104
|
-
</motion.div>
|
|
105
|
-
<FormList
|
|
106
|
-
initialValues={[
|
|
107
|
-
{
|
|
108
|
-
el: "sdfsdf",
|
|
109
|
-
d: { child: "Test Child" },
|
|
110
|
-
},
|
|
111
|
-
]}
|
|
112
|
-
name="arr"
|
|
113
|
-
>
|
|
114
|
-
{(fields, { add, remove, move }) => (
|
|
115
|
-
<div>
|
|
116
|
-
{fields.map((field, index) => (
|
|
117
|
-
<div key={field.key} style={{ marginBottom: 8 }}>
|
|
118
|
-
<FormItem name={`${field.name}.el`} initialValue={"Chém gió"}>
|
|
119
|
-
<InputWrapper>
|
|
120
|
-
<Input placeholder="Item value" style={{ width: 200 }} />
|
|
121
|
-
</InputWrapper>
|
|
122
|
-
</FormItem>
|
|
123
|
-
<FormItem
|
|
124
|
-
name={`${field.name}.d.child`}
|
|
125
|
-
initialValue={"Con của item"}
|
|
126
|
-
>
|
|
127
|
-
<InputWrapper>
|
|
128
|
-
<Input placeholder="Item value" style={{ width: 200 }} />
|
|
129
|
-
</InputWrapper>
|
|
130
|
-
</FormItem>
|
|
131
|
-
<Button
|
|
132
|
-
onClick={() => remove({ index })}
|
|
133
|
-
style={{ marginLeft: 8 }}
|
|
134
|
-
>
|
|
135
|
-
Remove
|
|
136
|
-
</Button>
|
|
137
|
-
{index > 0 && (
|
|
138
|
-
<Button
|
|
139
|
-
onClick={() => move({ from: index, to: index - 1 })}
|
|
140
|
-
style={{ marginLeft: 8 }}
|
|
141
|
-
>
|
|
142
|
-
Move Up
|
|
143
|
-
</Button>
|
|
144
|
-
)}
|
|
145
|
-
{index < fields.length - 1 && (
|
|
146
|
-
<Button
|
|
147
|
-
onClick={() => move({ from: index, to: index + 1 })}
|
|
148
|
-
style={{ marginLeft: 8 }}
|
|
149
|
-
>
|
|
150
|
-
Move Down
|
|
151
|
-
</Button>
|
|
152
|
-
)}
|
|
153
|
-
</div>
|
|
154
|
-
))}
|
|
155
|
-
<Button onClick={() => add(fields.length)}>Add Item</Button>
|
|
156
|
-
</div>
|
|
157
|
-
)}
|
|
158
|
-
</FormList>
|
|
159
|
-
<TestDialog />
|
|
160
|
-
<Button
|
|
161
|
-
onClick={() => {
|
|
162
|
-
form?.setFieldValue("arr", [
|
|
163
|
-
{ el: "Set Item 1" },
|
|
164
|
-
{ el: "Set Item 2" },
|
|
165
|
-
{ el: "Set Item 3" },
|
|
166
|
-
]);
|
|
167
|
-
}}
|
|
168
|
-
>
|
|
169
|
-
Test set array list value
|
|
170
|
-
</Button>
|
|
171
|
-
<motion.div
|
|
172
|
-
initial={{ opacity: 0 }}
|
|
173
|
-
animate={{ opacity: 1 }}
|
|
174
|
-
exit={{ opacity: 0 }}
|
|
175
|
-
transition={{ duration: 1.5 }}
|
|
176
|
-
>
|
|
177
|
-
<Form.Item
|
|
178
|
-
valuePropName="checked"
|
|
179
|
-
getValueFromEvent={(_, checked) => checked}
|
|
180
|
-
name="checkControlledAfterInit"
|
|
181
|
-
controlAfterInit={true}
|
|
182
|
-
initialValue={true}
|
|
183
|
-
hidden
|
|
184
|
-
>
|
|
185
|
-
<Checkbox />
|
|
186
|
-
</Form.Item>
|
|
187
|
-
</motion.div>
|
|
188
|
-
<TestFormWatch />
|
|
189
|
-
<Button
|
|
190
|
-
onClick={() => {
|
|
191
|
-
const current = form?.getFieldValue("checkControlledAfterInit");
|
|
192
|
-
console.log("Toggle controlled after init: ", current);
|
|
193
|
-
form?.setFieldValue("checkControlledAfterInit", !current);
|
|
194
|
-
}}
|
|
195
|
-
>
|
|
196
|
-
Toggle
|
|
197
|
-
</Button>
|
|
198
|
-
<Button htmlType="submit">Submit</Button>
|
|
199
|
-
<Button
|
|
200
|
-
onClick={() => {
|
|
201
|
-
form?.resetFields?.();
|
|
202
|
-
}}
|
|
203
|
-
>
|
|
204
|
-
Reset
|
|
205
|
-
</Button>
|
|
206
|
-
</Form>
|
|
33
|
+
<CommonTest />
|
|
34
|
+
{/* <Form formName="TestDialog" >
|
|
35
|
+
<TestDialog />
|
|
36
|
+
</Form> */}
|
|
207
37
|
|
|
208
38
|
<TestListener />
|
|
39
|
+
<TestWrapperFormItem />
|
|
209
40
|
</div>
|
|
210
41
|
);
|
|
211
42
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { isNil } from "lodash";
|
|
2
|
+
import type { ComponentProps, FC, ReactElement } from "react";
|
|
3
|
+
import { cloneElement, Fragment, useEffect, useRef, useState } from "react";
|
|
3
4
|
import { v4 } from "uuid";
|
|
4
5
|
import useFormItemControl from "../../hooks/useFormItemControl";
|
|
5
6
|
import type { ValidationRule } from "../../types/public";
|
|
6
7
|
|
|
7
|
-
export
|
|
8
|
+
export type BaseFormItemProps = {
|
|
8
9
|
children: ReactElement<any>;
|
|
9
10
|
name: string;
|
|
10
11
|
formName?: string;
|
|
@@ -16,10 +17,129 @@ export interface FormItemProps {
|
|
|
16
17
|
controlAfterInit?: boolean;
|
|
17
18
|
hidden?: boolean;
|
|
18
19
|
collectOnHidden?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type FormItemProps<TCustomWrapper extends FC<any> | undefined> =
|
|
23
|
+
BaseFormItemProps &
|
|
24
|
+
(
|
|
25
|
+
| {
|
|
26
|
+
Component?: undefined;
|
|
27
|
+
}
|
|
28
|
+
| ({
|
|
29
|
+
Component: TCustomWrapper;
|
|
30
|
+
} & Omit<ComponentProps<TCustomWrapper>, keyof BaseFormItemProps>)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
function BaseFormItem({
|
|
34
|
+
children,
|
|
35
|
+
|
|
36
|
+
name,
|
|
37
|
+
elementRef: elRef,
|
|
38
|
+
|
|
39
|
+
valuePropName,
|
|
40
|
+
getValueFromEvent,
|
|
41
|
+
onChange,
|
|
42
|
+
value,
|
|
43
|
+
isDirty,
|
|
44
|
+
errors,
|
|
45
|
+
onFocus,
|
|
46
|
+
state,
|
|
47
|
+
submitState,
|
|
48
|
+
isTouched,
|
|
49
|
+
}: any) {
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
console.log("Base Form Item: ", { name, value });
|
|
52
|
+
}, [value]);
|
|
53
|
+
return cloneElement(children, {
|
|
54
|
+
name,
|
|
55
|
+
ref: elRef,
|
|
56
|
+
[valuePropName]: value,
|
|
57
|
+
onChange: (...args: any[]) => {
|
|
58
|
+
let val = args[0];
|
|
59
|
+
if (getValueFromEvent && typeof getValueFromEvent === "function") {
|
|
60
|
+
val = getValueFromEvent(...args);
|
|
61
|
+
} else {
|
|
62
|
+
const e = args[0];
|
|
63
|
+
if (e && e.target) {
|
|
64
|
+
val = e.target.value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
onChange(val);
|
|
68
|
+
},
|
|
69
|
+
// onFocus: () => {
|
|
70
|
+
// setIsTouched(true);
|
|
71
|
+
// },
|
|
72
|
+
// isTouched: isTouched,
|
|
73
|
+
isDirty: isDirty,
|
|
74
|
+
// errors: errors,
|
|
75
|
+
// formState,
|
|
76
|
+
|
|
77
|
+
errors,
|
|
78
|
+
onFocus,
|
|
79
|
+
validateState: state,
|
|
80
|
+
submitState,
|
|
81
|
+
isTouched: isTouched,
|
|
82
|
+
} as any);
|
|
19
83
|
}
|
|
20
84
|
|
|
21
|
-
|
|
85
|
+
function FormItemWithWrapper<TComponent extends FC<any>>({
|
|
22
86
|
children,
|
|
87
|
+
|
|
88
|
+
name,
|
|
89
|
+
elementRef: elRef,
|
|
90
|
+
|
|
91
|
+
valuePropName,
|
|
92
|
+
getValueFromEvent,
|
|
93
|
+
onChange,
|
|
94
|
+
value,
|
|
95
|
+
isDirty,
|
|
96
|
+
errors,
|
|
97
|
+
onFocus,
|
|
98
|
+
state,
|
|
99
|
+
submitState,
|
|
100
|
+
isTouched,
|
|
101
|
+
Component,
|
|
102
|
+
...props
|
|
103
|
+
}: any) {
|
|
104
|
+
return (
|
|
105
|
+
<Component {...props}>
|
|
106
|
+
{cloneElement(children, {
|
|
107
|
+
name,
|
|
108
|
+
ref: elRef,
|
|
109
|
+
[valuePropName]: value,
|
|
110
|
+
onChange: (...args: any[]) => {
|
|
111
|
+
let val = args[0];
|
|
112
|
+
if (getValueFromEvent && typeof getValueFromEvent === "function") {
|
|
113
|
+
val = getValueFromEvent(...args);
|
|
114
|
+
} else {
|
|
115
|
+
const e = args[0];
|
|
116
|
+
if (e && e.target) {
|
|
117
|
+
val = e.target.value;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
onChange(val);
|
|
121
|
+
},
|
|
122
|
+
// onFocus: () => {
|
|
123
|
+
// setIsTouched(true);
|
|
124
|
+
// },
|
|
125
|
+
// isTouched: isTouched,
|
|
126
|
+
isDirty: isDirty,
|
|
127
|
+
// errors: errors,
|
|
128
|
+
// formState,
|
|
129
|
+
|
|
130
|
+
errors,
|
|
131
|
+
onFocus,
|
|
132
|
+
validateState: state,
|
|
133
|
+
submitState,
|
|
134
|
+
isTouched: isTouched,
|
|
135
|
+
} as any)}
|
|
136
|
+
</Component>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default function FormItem<TCustomWrapper extends FC<any> | undefined>({
|
|
141
|
+
children,
|
|
142
|
+
Component,
|
|
23
143
|
name,
|
|
24
144
|
formName,
|
|
25
145
|
initialValue,
|
|
@@ -30,10 +150,12 @@ export default function FormItem({
|
|
|
30
150
|
controlAfterInit = false,
|
|
31
151
|
hidden,
|
|
32
152
|
collectOnHidden,
|
|
33
|
-
|
|
153
|
+
...props
|
|
154
|
+
}: FormItemProps<TCustomWrapper>) {
|
|
155
|
+
const [formItemId] = useState(externalFormItemId ?? v4());
|
|
156
|
+
|
|
34
157
|
const elRef = useRef<any>(null);
|
|
35
158
|
|
|
36
|
-
const [formItemId] = useState(externalFormItemId ?? v4());
|
|
37
159
|
const {
|
|
38
160
|
value,
|
|
39
161
|
onChange,
|
|
@@ -54,60 +176,52 @@ export default function FormItem({
|
|
|
54
176
|
hidden,
|
|
55
177
|
collectOnHidden,
|
|
56
178
|
});
|
|
57
|
-
// console.log("re-render", formName, name);
|
|
58
|
-
|
|
59
|
-
// useEffect(() => {
|
|
60
|
-
// console.log({ value });
|
|
61
|
-
// }, [value]);
|
|
62
179
|
|
|
63
|
-
// useEffect(() => {
|
|
64
|
-
// console.log("isInitied changed: ", {
|
|
65
|
-
// isInitied,
|
|
66
|
-
// name,
|
|
67
|
-
// value,
|
|
68
|
-
// controlAfterInit,
|
|
69
|
-
// });
|
|
70
|
-
// }, [isInitied]);
|
|
71
180
|
return (
|
|
72
181
|
<Fragment
|
|
73
|
-
key={`control-after-init-${Boolean(controlAfterInit && isInitied) ? "1" : "0"}-${
|
|
182
|
+
key={`control-after-init-${Boolean(controlAfterInit && isInitied) ? "1" : "0"}-${externalFormItemId}`}
|
|
74
183
|
>
|
|
75
|
-
{!hidden && children
|
|
76
|
-
?
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
onFocus
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
184
|
+
{!hidden && children ? (
|
|
185
|
+
isNil(Component) ? (
|
|
186
|
+
<BaseFormItem
|
|
187
|
+
elementRef={elRef}
|
|
188
|
+
name={name}
|
|
189
|
+
valuePropName={valuePropName}
|
|
190
|
+
getValueFromEvent={getValueFromEvent}
|
|
191
|
+
value={value}
|
|
192
|
+
onChange={onChange}
|
|
193
|
+
errors={errors}
|
|
194
|
+
state={state}
|
|
195
|
+
onFocus={onFocus}
|
|
196
|
+
isDirty={isDirty}
|
|
197
|
+
submitState={submitState}
|
|
198
|
+
isTouched={isTouched}
|
|
199
|
+
formItemId={formItemId}
|
|
200
|
+
>
|
|
201
|
+
{children}
|
|
202
|
+
</BaseFormItem>
|
|
203
|
+
) : (
|
|
204
|
+
<FormItemWithWrapper
|
|
205
|
+
elementRef={elRef}
|
|
206
|
+
name={name}
|
|
207
|
+
valuePropName={valuePropName}
|
|
208
|
+
getValueFromEvent={getValueFromEvent}
|
|
209
|
+
value={value}
|
|
210
|
+
onChange={onChange}
|
|
211
|
+
errors={errors}
|
|
212
|
+
state={state}
|
|
213
|
+
onFocus={onFocus}
|
|
214
|
+
isDirty={isDirty}
|
|
215
|
+
submitState={submitState}
|
|
216
|
+
isTouched={isTouched}
|
|
217
|
+
formItemId={formItemId}
|
|
218
|
+
Component={Component}
|
|
219
|
+
{...props}
|
|
220
|
+
>
|
|
221
|
+
{children}
|
|
222
|
+
</FormItemWithWrapper>
|
|
223
|
+
)
|
|
224
|
+
) : null}
|
|
111
225
|
</Fragment>
|
|
112
226
|
);
|
|
113
227
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { get, has, isNil } from "lodash";
|
|
2
2
|
import { useTaskEffect } from "minh-custom-hooks-release";
|
|
3
|
-
import { useEffect, useMemo, type RefObject } from "react";
|
|
3
|
+
import { useEffect, useLayoutEffect, useMemo, type RefObject } from "react";
|
|
4
4
|
import { useShallow } from "zustand/react/shallow"; // Import useShallow
|
|
5
5
|
import {
|
|
6
6
|
IS_ALPHABET_STRING_AND_NUMBER_REGEX,
|
|
@@ -75,6 +75,9 @@ export default function useFormItemControl<T = any>({
|
|
|
75
75
|
// getFormState,
|
|
76
76
|
isStateInitied,
|
|
77
77
|
submitState,
|
|
78
|
+
getListener,
|
|
79
|
+
revokeListener,
|
|
80
|
+
clearObjKeyItem,
|
|
78
81
|
} = useFormStore(
|
|
79
82
|
useShallow((state) => {
|
|
80
83
|
return {
|
|
@@ -94,6 +97,9 @@ export default function useFormItemControl<T = any>({
|
|
|
94
97
|
state.formStates?.[
|
|
95
98
|
formName || form?.formName || contextForm?.formName
|
|
96
99
|
]?.submitState,
|
|
100
|
+
getListener: state.getListener,
|
|
101
|
+
revokeListener: state.revokeListener,
|
|
102
|
+
clearObjKeyItem: state.clearObjKeyItem,
|
|
97
103
|
};
|
|
98
104
|
}),
|
|
99
105
|
);
|
|
@@ -566,7 +572,8 @@ export default function useFormItemControl<T = any>({
|
|
|
566
572
|
}
|
|
567
573
|
}, [isStateInitied]);
|
|
568
574
|
|
|
569
|
-
|
|
575
|
+
useLayoutEffect(() => {
|
|
576
|
+
console.log("Component mount: ", name, formItemId, listener);
|
|
570
577
|
if (!listener) {
|
|
571
578
|
setListener({
|
|
572
579
|
onChange,
|
|
@@ -584,12 +591,12 @@ export default function useFormItemControl<T = any>({
|
|
|
584
591
|
}
|
|
585
592
|
|
|
586
593
|
return () => {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
}
|
|
592
|
-
}
|
|
594
|
+
revokeListener(formItemId, (listener, same) => {
|
|
595
|
+
if (!same.length) {
|
|
596
|
+
console.log("Trigger after revoke: ", listener, same);
|
|
597
|
+
clearObjKeyItem(listener.formName, listener.name);
|
|
598
|
+
}
|
|
599
|
+
});
|
|
593
600
|
};
|
|
594
601
|
|
|
595
602
|
// return () => {
|
|
@@ -598,15 +605,15 @@ export default function useFormItemControl<T = any>({
|
|
|
598
605
|
// };
|
|
599
606
|
}, []);
|
|
600
607
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
608
|
+
useEffect(() => {
|
|
609
|
+
if (listener) {
|
|
610
|
+
setListener({
|
|
611
|
+
formItemId,
|
|
612
|
+
hidden,
|
|
613
|
+
collectOnHidden,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}, [hidden, collectOnHidden]);
|
|
610
617
|
|
|
611
618
|
useEffect(() => {
|
|
612
619
|
if (listener) {
|
package/src/providers/Form.tsx
CHANGED
|
@@ -467,6 +467,8 @@ export default function Form<T = any>({
|
|
|
467
467
|
formName,
|
|
468
468
|
}}
|
|
469
469
|
>
|
|
470
|
+
<FormCleanUp />
|
|
471
|
+
|
|
470
472
|
{FormElement ? (
|
|
471
473
|
<FormElement
|
|
472
474
|
onSubmit={(e) => {
|
|
@@ -492,7 +494,6 @@ export default function Form<T = any>({
|
|
|
492
494
|
{children}
|
|
493
495
|
</form>
|
|
494
496
|
)}
|
|
495
|
-
<FormCleanUp />
|
|
496
497
|
</FormContext.Provider>
|
|
497
498
|
);
|
|
498
499
|
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { Button, Checkbox, Input } from "antd";
|
|
2
|
+
import { motion } from "framer-motion";
|
|
3
|
+
import FormItem from "../components/Form/FormItem";
|
|
4
|
+
import FormList from "../components/Form/FormList";
|
|
5
|
+
import InputWrapper from "../components/Form/InputWrapper";
|
|
6
|
+
import Form from "../providers/Form";
|
|
7
|
+
|
|
8
|
+
type Props = {};
|
|
9
|
+
|
|
10
|
+
function CommonTest({}: Props) {
|
|
11
|
+
const [form] = Form.useForm("form1");
|
|
12
|
+
|
|
13
|
+
const watchCheckBox = Form.useWatch("checkControlledAfterInit", "form1");
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Form
|
|
17
|
+
initialValues={{
|
|
18
|
+
TestData: "",
|
|
19
|
+
numericCode: "",
|
|
20
|
+
// arr: [{ el: "Item 1" }, { el: "Item 2" }],
|
|
21
|
+
}}
|
|
22
|
+
onFinish={(values) => {
|
|
23
|
+
console.log(values);
|
|
24
|
+
}}
|
|
25
|
+
formName={"form1"}
|
|
26
|
+
// hidden
|
|
27
|
+
>
|
|
28
|
+
<FormItem
|
|
29
|
+
name={"username"}
|
|
30
|
+
rules={[
|
|
31
|
+
{
|
|
32
|
+
required: true,
|
|
33
|
+
message: "Test",
|
|
34
|
+
},
|
|
35
|
+
]}
|
|
36
|
+
initialValue={"283746"}
|
|
37
|
+
// hidden
|
|
38
|
+
>
|
|
39
|
+
<InputWrapper>
|
|
40
|
+
<Input />
|
|
41
|
+
</InputWrapper>
|
|
42
|
+
</FormItem>
|
|
43
|
+
|
|
44
|
+
{/* Numberic test */}
|
|
45
|
+
<FormItem
|
|
46
|
+
name={"numericCode"}
|
|
47
|
+
rules={[
|
|
48
|
+
{ required: true, message: "Vui lòng nhập mã" },
|
|
49
|
+
{
|
|
50
|
+
pattern: /^\d+$/,
|
|
51
|
+
message: "Chỉ cho phép chuỗi số",
|
|
52
|
+
},
|
|
53
|
+
]}
|
|
54
|
+
>
|
|
55
|
+
<InputWrapper>
|
|
56
|
+
<Input placeholder="Mã chỉ gồm số" style={{ width: 200 }} />
|
|
57
|
+
</InputWrapper>
|
|
58
|
+
</FormItem>
|
|
59
|
+
|
|
60
|
+
{/* Motion Test */}
|
|
61
|
+
<motion.div
|
|
62
|
+
initial={{ opacity: 0 }}
|
|
63
|
+
animate={{ opacity: 1 }}
|
|
64
|
+
exit={{ opacity: 0 }}
|
|
65
|
+
transition={{ duration: 1 }}
|
|
66
|
+
>
|
|
67
|
+
<FormItem name="motionTest" controlAfterInit initialValue={"1234134"}>
|
|
68
|
+
<InputWrapper>
|
|
69
|
+
<Input placeholder="Motion Test" style={{ width: 200 }} />
|
|
70
|
+
</InputWrapper>
|
|
71
|
+
</FormItem>
|
|
72
|
+
</motion.div>
|
|
73
|
+
<FormList
|
|
74
|
+
initialValues={[
|
|
75
|
+
{
|
|
76
|
+
el: "sdfsdf",
|
|
77
|
+
d: { child: "Test Child" },
|
|
78
|
+
},
|
|
79
|
+
]}
|
|
80
|
+
name="arr"
|
|
81
|
+
>
|
|
82
|
+
{(fields, { add, remove, move }) => (
|
|
83
|
+
<div>
|
|
84
|
+
{fields.map((field, index) => (
|
|
85
|
+
<div key={field.key} style={{ marginBottom: 8 }}>
|
|
86
|
+
<FormItem name={`${field.name}.el`} initialValue={"Chém gió"}>
|
|
87
|
+
<InputWrapper>
|
|
88
|
+
<Input placeholder="Item value" style={{ width: 200 }} />
|
|
89
|
+
</InputWrapper>
|
|
90
|
+
</FormItem>
|
|
91
|
+
<FormItem
|
|
92
|
+
name={`${field.name}.d.child`}
|
|
93
|
+
initialValue={"Con của item"}
|
|
94
|
+
>
|
|
95
|
+
<InputWrapper>
|
|
96
|
+
<Input placeholder="Item value" style={{ width: 200 }} />
|
|
97
|
+
</InputWrapper>
|
|
98
|
+
</FormItem>
|
|
99
|
+
<Button
|
|
100
|
+
onClick={() => remove({ index })}
|
|
101
|
+
style={{ marginLeft: 8 }}
|
|
102
|
+
>
|
|
103
|
+
Remove
|
|
104
|
+
</Button>
|
|
105
|
+
{index > 0 && (
|
|
106
|
+
<Button
|
|
107
|
+
onClick={() => move({ from: index, to: index - 1 })}
|
|
108
|
+
style={{ marginLeft: 8 }}
|
|
109
|
+
>
|
|
110
|
+
Move Up
|
|
111
|
+
</Button>
|
|
112
|
+
)}
|
|
113
|
+
{index < fields.length - 1 && (
|
|
114
|
+
<Button
|
|
115
|
+
onClick={() => move({ from: index, to: index + 1 })}
|
|
116
|
+
style={{ marginLeft: 8 }}
|
|
117
|
+
>
|
|
118
|
+
Move Down
|
|
119
|
+
</Button>
|
|
120
|
+
)}
|
|
121
|
+
</div>
|
|
122
|
+
))}
|
|
123
|
+
<Button onClick={() => add(fields.length)}>Add Item</Button>
|
|
124
|
+
</div>
|
|
125
|
+
)}
|
|
126
|
+
</FormList>
|
|
127
|
+
<Button
|
|
128
|
+
onClick={() => {
|
|
129
|
+
form?.setFieldValue("arr", [
|
|
130
|
+
{ el: "Set Item 1" },
|
|
131
|
+
{ el: "Set Item 2" },
|
|
132
|
+
{ el: "Set Item 3" },
|
|
133
|
+
]);
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
Test set array list value
|
|
137
|
+
</Button>
|
|
138
|
+
<motion.div
|
|
139
|
+
initial={{ opacity: 0 }}
|
|
140
|
+
animate={{ opacity: 1 }}
|
|
141
|
+
exit={{ opacity: 0 }}
|
|
142
|
+
transition={{ duration: 1.5 }}
|
|
143
|
+
>
|
|
144
|
+
<Form.Item
|
|
145
|
+
valuePropName="checked"
|
|
146
|
+
getValueFromEvent={(_, checked) => checked}
|
|
147
|
+
name="checkControlledAfterInit"
|
|
148
|
+
controlAfterInit={true}
|
|
149
|
+
initialValue={true}
|
|
150
|
+
hidden
|
|
151
|
+
>
|
|
152
|
+
<Checkbox />
|
|
153
|
+
</Form.Item>
|
|
154
|
+
</motion.div>
|
|
155
|
+
{/* <TestFormWatch /> */}
|
|
156
|
+
<Button
|
|
157
|
+
onClick={() => {
|
|
158
|
+
const current = form?.getFieldValue("checkControlledAfterInit");
|
|
159
|
+
console.log("Toggle controlled after init: ", current);
|
|
160
|
+
form?.setFieldValue("checkControlledAfterInit", !current);
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
Toggle
|
|
164
|
+
</Button>
|
|
165
|
+
<Button htmlType="submit">Submit</Button>
|
|
166
|
+
<Button
|
|
167
|
+
onClick={() => {
|
|
168
|
+
form?.resetFields?.();
|
|
169
|
+
}}
|
|
170
|
+
>
|
|
171
|
+
Reset
|
|
172
|
+
</Button>
|
|
173
|
+
</Form>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export default CommonTest;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Button, Col, Input, Row } from "antd";
|
|
2
|
+
import { useToggle } from "minh-custom-hooks-release";
|
|
3
|
+
import Form from "../providers/Form";
|
|
4
|
+
|
|
5
|
+
type Props = {};
|
|
6
|
+
|
|
7
|
+
function TestWrapperFormItem({}: Props) {
|
|
8
|
+
const { state, toggle } = useToggle(false);
|
|
9
|
+
return (
|
|
10
|
+
<Form
|
|
11
|
+
onFinish={(values, all) => {
|
|
12
|
+
console.log(values, all);
|
|
13
|
+
}}
|
|
14
|
+
formName="testWrapper"
|
|
15
|
+
>
|
|
16
|
+
<Row>
|
|
17
|
+
<Form.Item
|
|
18
|
+
hidden={!state}
|
|
19
|
+
name="test"
|
|
20
|
+
collectOnHidden={false}
|
|
21
|
+
initialValue={"test"}
|
|
22
|
+
Component={Col}
|
|
23
|
+
xs={12}
|
|
24
|
+
>
|
|
25
|
+
<Input />
|
|
26
|
+
</Form.Item>
|
|
27
|
+
</Row>
|
|
28
|
+
<Button htmlType="submit">Submit</Button>
|
|
29
|
+
<Button onClick={toggle}>{state ? "Off" : "On"}</Button>
|
|
30
|
+
</Form>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default TestWrapperFormItem;
|