react-form-manage 1.0.8-beta.27 → 1.0.8-beta.28
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 +28 -0
- package/dist/constants/form.d.ts +1 -1
- package/dist/hooks/useFormItemControl.d.ts +5 -2
- package/dist/providers/Form.d.ts +5 -1
- package/dist/providers/Form.js +145 -39
- package/dist/test/testSetValue/TestCase10_SetFieldValues_ComplexNested.d.ts +21 -0
- package/dist/test/testSetValue/TestCase10_SetFieldValues_ComplexNested.js +61 -0
- package/dist/test/testSetValue/TestCase1_PlainObjectToPrimitives.d.ts +16 -0
- package/dist/test/testSetValue/TestCase1_PlainObjectToPrimitives.js +18 -0
- package/dist/test/testSetValue/TestCase2_PlainObjectToFormList.d.ts +21 -0
- package/dist/test/testSetValue/TestCase2_PlainObjectToFormList.js +33 -0
- package/dist/test/testSetValue/TestCase3_ArrayNonListenerToPrimitives.d.ts +21 -0
- package/dist/test/testSetValue/TestCase3_ArrayNonListenerToPrimitives.js +26 -0
- package/dist/test/testSetValue/TestCase4_PlainObjectRemovedFields.d.ts +20 -0
- package/dist/test/testSetValue/TestCase4_PlainObjectRemovedFields.js +32 -0
- package/dist/test/testSetValue/TestCase5_FormListRemovedItems.d.ts +22 -0
- package/dist/test/testSetValue/TestCase5_FormListRemovedItems.js +29 -0
- package/dist/test/testSetValue/TestCase6_NestedFormListRemoved.d.ts +28 -0
- package/dist/test/testSetValue/TestCase6_NestedFormListRemoved.js +36 -0
- package/dist/test/testSetValue/TestCase7_SetFieldValues_MixedStructure.d.ts +17 -0
- package/dist/test/testSetValue/TestCase7_SetFieldValues_MixedStructure.js +33 -0
- package/dist/test/testSetValue/TestCase8_SetFieldValues_NestedObject.d.ts +27 -0
- package/dist/test/testSetValue/TestCase8_SetFieldValues_NestedObject.js +57 -0
- package/dist/test/testSetValue/TestCase9_SetFieldValues_MultipleArrays.d.ts +25 -0
- package/dist/test/testSetValue/TestCase9_SetFieldValues_MultipleArrays.js +46 -0
- package/dist/test/testSetValue/index.d.ts +2 -0
- package/dist/test/testSetValue/index.js +28 -0
- package/dist/utils/obj.util.d.ts +28 -0
- package/dist/utils/obj.util.js +43 -0
- package/package.json +1 -1
- package/src/App.tsx +27 -17
- package/src/DEEP_TRIGGER_LOGIC.md +573 -0
- package/src/constants/form.ts +1 -1
- package/src/hooks/useFormItemControl.ts +6 -1
- package/src/providers/Form.tsx +358 -51
- package/src/test/testSetValue/TestCase10_SetFieldValues_ComplexNested.tsx +206 -0
- package/src/test/testSetValue/TestCase1_PlainObjectToPrimitives.tsx +72 -0
- package/src/test/testSetValue/TestCase2_PlainObjectToFormList.tsx +114 -0
- package/src/test/testSetValue/TestCase3_ArrayNonListenerToPrimitives.tsx +99 -0
- package/src/test/testSetValue/TestCase4_PlainObjectRemovedFields.tsx +112 -0
- package/src/test/testSetValue/TestCase5_FormListRemovedItems.tsx +119 -0
- package/src/test/testSetValue/TestCase6_NestedFormListRemoved.tsx +185 -0
- package/src/test/testSetValue/TestCase7_SetFieldValues_MixedStructure.tsx +110 -0
- package/src/test/testSetValue/TestCase8_SetFieldValues_NestedObject.tsx +162 -0
- package/src/test/testSetValue/TestCase9_SetFieldValues_MultipleArrays.tsx +173 -0
- package/src/test/testSetValue/index.tsx +100 -0
- package/src/utils/obj.util.ts +109 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.0.8-beta.28] - 2026-02-09
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **Deep Trigger Set Value**: Implement recursive value setting with comprehensive listener triggering
|
|
10
|
+
- `setFieldValue` with `deepTrigger: true` option for recursive listener notification
|
|
11
|
+
- Support for plain objects, arrays, FormLists, and nested structures
|
|
12
|
+
- Proper cleanup for removed fields and array items
|
|
13
|
+
- Edge case handling: removed object fields, nested FormList items
|
|
14
|
+
- **Enhanced setFieldValues**: Improved batch value setting logic
|
|
15
|
+
- Automatically detects arrays and uses deep trigger
|
|
16
|
+
- Traverses object structure and stops at arrays
|
|
17
|
+
- Primitives trigger onChange, arrays use handleDeepTriggerSet
|
|
18
|
+
- **Utility Functions**: New path collection utilities in obj.util.ts
|
|
19
|
+
- `getAllPathsIncludingContainers`: Get all paths including intermediate containers
|
|
20
|
+
- `getAllPathsStopAtArray`: Get paths but stop traversal at arrays
|
|
21
|
+
- **Array Index Notation**: Changed from `[index]` to `.index` notation for consistency
|
|
22
|
+
- **Documentation**: Added comprehensive DEEP_TRIGGER_LOGIC.md with 6 detailed case studies
|
|
23
|
+
- **Test Suite**: Created 10 test cases covering all deep trigger scenarios
|
|
24
|
+
|
|
25
|
+
### Technical Details
|
|
26
|
+
|
|
27
|
+
- Deep trigger handles 5 core value types: primitives, plain objects, array listeners (FormList), non-listener arrays, and class instances
|
|
28
|
+
- Hierarchical trigger order: field level → item/index level → property level
|
|
29
|
+
- Recursive cleanup for removed nested structures
|
|
30
|
+
- Options support for controlling dirty state triggering
|
|
31
|
+
|
|
5
32
|
## [1.0.8-beta.27] - 2026-02-04
|
|
6
33
|
|
|
7
34
|
### Features
|
|
35
|
+
|
|
8
36
|
- Add `useWatchNormalize` hook for watching and normalizing form data
|
|
9
37
|
- Support custom normalization functions for automatic value transformation
|
|
10
38
|
- Simplifies data format conversion during form value watching
|
package/dist/constants/form.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type RefObject } from "react";
|
|
2
2
|
import type { FormInstance } from "../stores/formStore";
|
|
3
3
|
import type { FormFieldError, SubmitState, ValidationRule } from "../types/public";
|
|
4
|
-
type AnyObject = Record<string, any>;
|
|
5
4
|
interface UseFormItemControlProps {
|
|
6
5
|
formName?: string;
|
|
7
6
|
form?: FormInstance;
|
|
@@ -13,9 +12,13 @@ interface UseFormItemControlProps {
|
|
|
13
12
|
hidden?: boolean;
|
|
14
13
|
collectOnHidden?: boolean;
|
|
15
14
|
}
|
|
15
|
+
export interface OnChangeOptions {
|
|
16
|
+
notTriggerDirty?: boolean;
|
|
17
|
+
initiedData?: boolean;
|
|
18
|
+
}
|
|
16
19
|
export interface UseFormItemControlReturn {
|
|
17
20
|
value: any;
|
|
18
|
-
onChange: (value: any, options?:
|
|
21
|
+
onChange: (value: any, options?: OnChangeOptions) => void;
|
|
19
22
|
state: any;
|
|
20
23
|
errors: FormFieldError[];
|
|
21
24
|
onFocus: () => void;
|
package/dist/providers/Form.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { ComponentType, FormHTMLAttributes, ReactNode } from "react";
|
|
2
2
|
import FormItem from "../components/Form/FormItem";
|
|
3
|
+
import { OnChangeOptions } from "../hooks/useFormItemControl";
|
|
3
4
|
import type { PublicFormInstance, UseFormItemStateWatchReturn } from "../types/public";
|
|
4
|
-
export type { FormFieldError, SubmitState, UseFormItemStateWatchReturn, ValidationRule
|
|
5
|
+
export type { FormFieldError, SubmitState, UseFormItemStateWatchReturn, ValidationRule } from "../types/public";
|
|
5
6
|
export declare const FormContext: import("react").Context<any>;
|
|
7
|
+
export interface SetFieldValueOptions extends OnChangeOptions {
|
|
8
|
+
deepTrigger?: boolean;
|
|
9
|
+
}
|
|
6
10
|
export interface FormProps<T = any> extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
|
|
7
11
|
collectHiddenFields?: boolean;
|
|
8
12
|
children: ReactNode;
|
package/dist/providers/Form.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { cloneDeep, filter, get, isEqual, isNil, isPlainObject, last, set, uniqBy } from "lodash";
|
|
2
|
+
import { cloneDeep, filter, get, isArray, isEqual, isNil, isPlainObject, last, set, uniqBy } from "lodash";
|
|
3
3
|
import { useTask } from "minh-custom-hooks-release";
|
|
4
4
|
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
|
5
5
|
import { flushSync } from "react-dom";
|
|
@@ -7,7 +7,7 @@ import { useShallow } from "zustand/react/shallow";
|
|
|
7
7
|
import FormItem from "../components/Form/FormItem";
|
|
8
8
|
import { SUBMIT_STATE } from "../constants/form";
|
|
9
9
|
import { useFormStore } from "../stores/formStore";
|
|
10
|
-
import { getAllNoneObjStringPath } from "../utils/obj.util";
|
|
10
|
+
import { getAllNoneObjStringPath, getAllPathsIncludingContainers, getAllPathsStopAtArray } from "../utils/obj.util";
|
|
11
11
|
const FormContext = createContext(null);
|
|
12
12
|
function Form({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, collectHiddenFields: formCollectHiddenFields = true, ...props }) {
|
|
13
13
|
const {
|
|
@@ -44,7 +44,137 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
44
44
|
getListeners: state.getListeners
|
|
45
45
|
};
|
|
46
46
|
}));
|
|
47
|
+
const handlePrimitiveValue = (name, value, options) => {
|
|
48
|
+
const listener = getListeners().find((l) => l.name === name && l.formName === formName);
|
|
49
|
+
if (listener) {
|
|
50
|
+
listener.onChange(value, options);
|
|
51
|
+
} else {
|
|
52
|
+
setData(formName, name, value);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const handleArrayListener = (name, value, options, coreRecursive) => {
|
|
56
|
+
const listener = getListeners().find((l) => l.name === name && l.formName === formName);
|
|
57
|
+
if (!listener)
|
|
58
|
+
return;
|
|
59
|
+
const currentValue = getFormItemValue(formName, name);
|
|
60
|
+
if (!isEqual(currentValue, value)) {
|
|
61
|
+
listener.onArrayChange(value, options);
|
|
62
|
+
value.forEach((item, index) => {
|
|
63
|
+
const itemName = `${name}.${index}`;
|
|
64
|
+
const itemListener = getListeners().find((l) => l.name === itemName && l.formName === formName);
|
|
65
|
+
if (itemListener) {
|
|
66
|
+
itemListener.onChange(item, options);
|
|
67
|
+
}
|
|
68
|
+
const nestedPaths = getAllPathsIncludingContainers(item);
|
|
69
|
+
nestedPaths.forEach((p) => {
|
|
70
|
+
if (coreRecursive) {
|
|
71
|
+
coreRecursive(`${itemName}.${p}`, get(item, p), options);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
if (isArray(currentValue) && currentValue.length > value.length) {
|
|
76
|
+
for (let index = value.length; index < currentValue.length; index++) {
|
|
77
|
+
const itemName = `${name}.${index}`;
|
|
78
|
+
if (coreRecursive) {
|
|
79
|
+
coreRecursive(itemName, void 0, options);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const handlePlainObject = (name, value, options, coreRecursive) => {
|
|
86
|
+
const listener = getListeners().find((l) => l.name === name && l.formName === formName);
|
|
87
|
+
if (listener && listener.type !== "array") {
|
|
88
|
+
listener.onChange(value, options);
|
|
89
|
+
}
|
|
90
|
+
const allPaths = getAllPathsIncludingContainers(value);
|
|
91
|
+
allPaths.forEach((p) => {
|
|
92
|
+
if (coreRecursive) {
|
|
93
|
+
const fullPath = `${name}.${p}`;
|
|
94
|
+
coreRecursive(fullPath, get(value, p), options);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
const previousValue = getFieldValue(name);
|
|
98
|
+
if (isPlainObject(previousValue)) {
|
|
99
|
+
const previousKeys = Object.keys(previousValue);
|
|
100
|
+
const newKeys = Object.keys(value);
|
|
101
|
+
const removedKeys = previousKeys.filter((k) => !newKeys.includes(k));
|
|
102
|
+
removedKeys.forEach((key) => {
|
|
103
|
+
if (coreRecursive) {
|
|
104
|
+
coreRecursive(`${name}.${key}`, void 0, options);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const handleNonListenerArray = (name, value, options, coreRecursive) => {
|
|
110
|
+
const previousValues = getFieldValue(name);
|
|
111
|
+
if (isArray(previousValues)) {
|
|
112
|
+
if (previousValues.length !== value.length || !isEqual(previousValues, value)) {
|
|
113
|
+
setData(formName, name, value);
|
|
114
|
+
}
|
|
115
|
+
value.forEach((item, index) => {
|
|
116
|
+
if (!isEqual(previousValues[index], item)) {
|
|
117
|
+
const itemName = `${name}.${index}`;
|
|
118
|
+
const itemListener = getListeners().find((l) => l.name === itemName && l.formName === formName);
|
|
119
|
+
if (itemListener) {
|
|
120
|
+
itemListener.onChange(item, options);
|
|
121
|
+
}
|
|
122
|
+
const nestedPaths = getAllPathsIncludingContainers(item);
|
|
123
|
+
nestedPaths.forEach((p) => {
|
|
124
|
+
if (coreRecursive) {
|
|
125
|
+
coreRecursive(`${itemName}.${p}`, get(item, p), options);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
if (previousValues.length > value.length) {
|
|
131
|
+
for (let index = value.length; index < previousValues.length; index++) {
|
|
132
|
+
const itemName = `${name}.${index}`;
|
|
133
|
+
const removedItem = previousValues[index];
|
|
134
|
+
const nestedPaths = getAllPathsIncludingContainers(removedItem);
|
|
135
|
+
nestedPaths.forEach((p) => {
|
|
136
|
+
if (coreRecursive) {
|
|
137
|
+
coreRecursive(`${itemName}.${p}`, void 0, options);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
if (coreRecursive) {
|
|
141
|
+
coreRecursive(itemName, void 0, options);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const deepTriggerSetCore = (name, value, options) => {
|
|
148
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || value === void 0) {
|
|
149
|
+
handlePrimitiveValue(name, value, options);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (isPlainObject(value)) {
|
|
153
|
+
const listener = getListeners().find((l) => l.name === name && l.formName === formName);
|
|
154
|
+
handlePlainObject(name, value, options, deepTriggerSetCore);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (Array.isArray(value)) {
|
|
158
|
+
const listener = getListeners().find((l) => l.name === name && l.formName === formName);
|
|
159
|
+
if (listener && listener.type === "array") {
|
|
160
|
+
handleArrayListener(name, value, options, deepTriggerSetCore);
|
|
161
|
+
} else if (!listener) {
|
|
162
|
+
handleNonListenerArray(name, value, options, deepTriggerSetCore);
|
|
163
|
+
} else {
|
|
164
|
+
handlePlainObject(name, value, options, deepTriggerSetCore);
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
handlePrimitiveValue(name, value, options);
|
|
169
|
+
};
|
|
170
|
+
const handleDeepTriggerSet = (name, value, options) => {
|
|
171
|
+
deepTriggerSetCore(name, value, options);
|
|
172
|
+
};
|
|
47
173
|
const setFieldValue = (name, value, options) => {
|
|
174
|
+
if (options == null ? void 0 : options.deepTrigger) {
|
|
175
|
+
handleDeepTriggerSet(name, value, options);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
48
178
|
const listener = getListeners().find((l) => l.name === name && l.formName === formName);
|
|
49
179
|
if (listener) {
|
|
50
180
|
if (listener.type === "array") {
|
|
@@ -64,52 +194,28 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
64
194
|
listener.onChange(value, options);
|
|
65
195
|
}
|
|
66
196
|
} else {
|
|
67
|
-
|
|
68
|
-
const allStringPath = getAllNoneObjStringPath(value);
|
|
69
|
-
allStringPath.forEach((p) => {
|
|
70
|
-
const findListener = getListeners().find((l) => l.name === `${name}.${p}` && l.formName === formName);
|
|
71
|
-
if (findListener) {
|
|
72
|
-
findListener.onChange(get(value, p), options);
|
|
73
|
-
} else {
|
|
74
|
-
setData(formName, `${name}.${p}`, get(value, p));
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
} else {
|
|
78
|
-
setData(formName, name, value);
|
|
79
|
-
}
|
|
197
|
+
setData(formName, name, value);
|
|
80
198
|
}
|
|
81
199
|
};
|
|
82
200
|
const setFieldValues = (values, options = { notTriggerDirty: false }) => {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
const
|
|
201
|
+
const allPaths = getAllPathsStopAtArray(values);
|
|
202
|
+
allPaths.forEach((path) => {
|
|
203
|
+
const pathValue = get(values, path);
|
|
204
|
+
if (Array.isArray(pathValue)) {
|
|
205
|
+
handleDeepTriggerSet(path, pathValue, options);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const listener = getListeners().find((l) => l.name === path && l.formName === formName);
|
|
86
209
|
if (listener) {
|
|
87
|
-
|
|
88
|
-
if (!isEqual(getFormItemValue(formName, p), get(values, p))) {
|
|
89
|
-
listener.onArrayChange(get(values, listener.name), options);
|
|
90
|
-
const nestedAllStringPath = getAllNoneObjStringPath(get(values, p));
|
|
91
|
-
nestedAllStringPath.forEach((np) => {
|
|
92
|
-
{
|
|
93
|
-
const findListener = getListeners().find((l) => l.name === `${p}.${np}` && l.formName === formName);
|
|
94
|
-
if (findListener) {
|
|
95
|
-
findListener.onChange(get(values, `${p}.${np}`), options);
|
|
96
|
-
} else {
|
|
97
|
-
setData(formName, `${p}.${np}`, get(values, `${p}.${np}`));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
} else {
|
|
103
|
-
listener.onChange(get(values, listener.name), options);
|
|
104
|
-
}
|
|
210
|
+
listener.onChange(pathValue, options);
|
|
105
211
|
} else {
|
|
106
|
-
setData(formName,
|
|
212
|
+
setData(formName, path, pathValue);
|
|
107
213
|
}
|
|
108
214
|
});
|
|
109
215
|
};
|
|
110
|
-
|
|
216
|
+
function getFieldValue(name) {
|
|
111
217
|
return getFormItemValue(formName, name);
|
|
112
|
-
}
|
|
218
|
+
}
|
|
113
219
|
const getFieldValues = (names = []) => {
|
|
114
220
|
return names.map((name) => ({
|
|
115
221
|
name,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type Props = {};
|
|
2
|
+
/**
|
|
3
|
+
* Test Case 10: setFieldValues với Complex Nested Structure
|
|
4
|
+
*
|
|
5
|
+
* Cấu trúc phức tạp:
|
|
6
|
+
* - config.appName (string)
|
|
7
|
+
* - config.version (string)
|
|
8
|
+
* - config.features (array) - deepTrigger
|
|
9
|
+
* - users (FormList array) - deepTrigger
|
|
10
|
+
* - users.0.name (string)
|
|
11
|
+
* - users.0.roles (array) - nested array trong FormList
|
|
12
|
+
*
|
|
13
|
+
* Test: setFieldValues với structure phức tạp nhiều cấp
|
|
14
|
+
*
|
|
15
|
+
* Kỳ vọng:
|
|
16
|
+
* - Primitives trigger onChange
|
|
17
|
+
* - Arrays ở mọi level đều gọi handleDeepTriggerSet
|
|
18
|
+
* - Nested arrays trong FormList được xử lý đúng
|
|
19
|
+
*/
|
|
20
|
+
declare function TestCase10_SetFieldValues_ComplexNested({}: Props): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export default TestCase10_SetFieldValues_ComplexNested;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
3
|
+
import { Button, Input, Typography } from "antd";
|
|
4
|
+
import FormList from "../../components/Form/FormList";
|
|
5
|
+
import Form from "../../providers/Form";
|
|
6
|
+
function TestCase10_SetFieldValues_ComplexNested({}) {
|
|
7
|
+
const [form] = Form.useForm("testCase10");
|
|
8
|
+
const handleTestSetFieldValues = () => {
|
|
9
|
+
form == null ? void 0 : form.setFieldValues({
|
|
10
|
+
config: {
|
|
11
|
+
appName: "My App",
|
|
12
|
+
version: "1.0.0",
|
|
13
|
+
features: ["auth", "api", "ui"]
|
|
14
|
+
},
|
|
15
|
+
users: [
|
|
16
|
+
{ name: "John", roles: ["admin", "editor"] },
|
|
17
|
+
{ name: "Jane", roles: ["viewer"] }
|
|
18
|
+
]
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
const handleTestUpdateStructure = () => {
|
|
22
|
+
form == null ? void 0 : form.setFieldValues({
|
|
23
|
+
config: {
|
|
24
|
+
appName: "Updated App",
|
|
25
|
+
version: "2.0.0",
|
|
26
|
+
features: ["auth", "api"]
|
|
27
|
+
// removed "ui"
|
|
28
|
+
},
|
|
29
|
+
users: [
|
|
30
|
+
{ name: "John", roles: ["admin"] }
|
|
31
|
+
// removed editor role + removed Jane user
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const handleClear = () => {
|
|
36
|
+
form == null ? void 0 : form.setFieldValues({
|
|
37
|
+
config: {
|
|
38
|
+
appName: "",
|
|
39
|
+
version: "",
|
|
40
|
+
features: []
|
|
41
|
+
},
|
|
42
|
+
users: []
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
return _jsxs(Box, { sx: { p: 2 }, children: [_jsx(Typography.Title, { level: 4, children: "Test Case 10: setFieldValues - Complex Nested" }), _jsx(Typography.Paragraph, { children: "Test setFieldValues v\u1EDBi structure ph\u1EE9c t\u1EA1p: nested objects + arrays + FormList" }), _jsxs(Form, { formName: "testCase10", children: [_jsxs(Box, { sx: { border: "2px solid #1890ff", p: 2, mb: 2, borderRadius: 1 }, children: [_jsx(Typography.Text, { strong: true, style: { fontSize: 16 }, children: "Config" }), _jsx(Form.Item, { name: "config.appName", label: "App Name", children: _jsx(Input, { placeholder: "Enter app name" }) }), _jsx(Form.Item, { name: "config.version", label: "Version", children: _jsx(Input, { placeholder: "Enter version" }) }), _jsxs(Box, { sx: { mt: 1 }, children: [_jsx(Typography.Text, { children: "Features (Array):" }), _jsx(Form.Item, { name: "config.features.0", children: _jsx(Input, { placeholder: "Feature 1" }) }), _jsx(Form.Item, { name: "config.features.1", children: _jsx(Input, { placeholder: "Feature 2" }) }), _jsx(Form.Item, { name: "config.features.2", children: _jsx(Input, { placeholder: "Feature 3" }) })] })] }), _jsxs(Box, { sx: { border: "2px solid #52c41a", p: 2, mb: 2, borderRadius: 1 }, children: [_jsx(Typography.Text, { strong: true, style: { fontSize: 16 }, children: "Users (FormList)" }), _jsx(FormList, { name: "users", children: (fields, { add, remove }) => _jsxs(Box, { children: [fields.map((field, index) => _jsxs(Box, { sx: {
|
|
46
|
+
border: "1px dashed #52c41a",
|
|
47
|
+
p: 1,
|
|
48
|
+
mb: 1,
|
|
49
|
+
borderRadius: 1
|
|
50
|
+
}, children: [_jsxs(Typography.Text, { children: ["User ", index + 1] }), _jsx(Form.Item, { name: `users.${index}.name`, label: "Name", children: _jsx(Input, { placeholder: "User name" }) }), _jsxs(Box, { sx: { ml: 2, bgcolor: "#f6ffed", p: 1, borderRadius: 1 }, children: [_jsx(Typography.Text, { children: "Roles (Nested Array):" }), _jsx(Form.Item, { name: `users.${index}.roles.0`, children: _jsx(Input, { placeholder: "Role 1" }) }), _jsx(Form.Item, { name: `users.${index}.roles.1`, children: _jsx(Input, { placeholder: "Role 2" }) })] }), _jsx(Button, { danger: true, size: "small", onClick: () => remove({ key: field.key }), children: "Remove User" })] }, field.key)), _jsx(Button, { type: "dashed", onClick: () => add(), children: "Add User" })] }) })] }), _jsxs(Box, { sx: { mt: 2, display: "flex", gap: 2, flexDirection: "column" }, children: [_jsx(Button, { type: "primary", onClick: handleTestSetFieldValues, children: "1. Set Complex Structure" }), _jsx(Button, { onClick: handleTestUpdateStructure, children: "2. Update with Cleanup" }), _jsx(Button, { danger: true, onClick: handleClear, children: "3. Clear All" })] }), _jsxs(Box, { sx: {
|
|
51
|
+
mt: 2,
|
|
52
|
+
p: 2,
|
|
53
|
+
bgcolor: "#e6fffb",
|
|
54
|
+
border: "1px solid #13c2c2",
|
|
55
|
+
borderRadius: 1
|
|
56
|
+
}, children: [_jsx(Typography.Text, { strong: true, children: "Expected Behavior:" }), _jsxs(Typography.Paragraph, { children: [_jsx("strong", { children: "setFieldValues logic:" }), _jsx("br", {}), "- Traverse object, d\u1EEBng t\u1EA1i m\u1ED7i array", _jsx("br", {}), "- Primitives: trigger onChange", _jsx("br", {}), "- Arrays: g\u1ECDi handleDeepTriggerSet", _jsx("br", {}), _jsx("br", {}), _jsx("strong", { children: "Update with Cleanup:" }), _jsx("br", {}), "- config.features.2 \u2192 undefined (removed)", _jsx("br", {}), "- users.1 \u2192 undefined (Jane removed)", _jsx("br", {}), "- users.0.roles.1 \u2192 undefined (editor removed)"] })] })] })] });
|
|
57
|
+
}
|
|
58
|
+
var stdin_default = TestCase10_SetFieldValues_ComplexNested;
|
|
59
|
+
export {
|
|
60
|
+
stdin_default as default
|
|
61
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type Props = {};
|
|
2
|
+
/**
|
|
3
|
+
* Test Case 1: Plain Object → Primitive Listeners
|
|
4
|
+
*
|
|
5
|
+
* Cấu trúc:
|
|
6
|
+
* - user.name (string)
|
|
7
|
+
* - user.age (number)
|
|
8
|
+
*
|
|
9
|
+
* Test: setFieldValue("user", {name: "John", age: 30}, {deepTrigger: true})
|
|
10
|
+
* Kỳ vọng:
|
|
11
|
+
* - Trigger "user" listener (nếu có)
|
|
12
|
+
* - Trigger "user.name" listener
|
|
13
|
+
* - Trigger "user.age" listener
|
|
14
|
+
*/
|
|
15
|
+
declare function TestCase1_PlainObjectToPrimitives({}: Props): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export default TestCase1_PlainObjectToPrimitives;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
3
|
+
import { Button, Input, Typography } from "antd";
|
|
4
|
+
import Form from "../../providers/Form";
|
|
5
|
+
function TestCase1_PlainObjectToPrimitives({}) {
|
|
6
|
+
const [form] = Form.useForm("testCase1");
|
|
7
|
+
const handleTestDeepTrigger = () => {
|
|
8
|
+
form == null ? void 0 : form.setFieldValue("user", { name: "John Doe", age: 30 }, { deepTrigger: true });
|
|
9
|
+
};
|
|
10
|
+
const handleTestNormalSet = () => {
|
|
11
|
+
form == null ? void 0 : form.setFieldValue("user", { name: "Jane Doe", age: 25 });
|
|
12
|
+
};
|
|
13
|
+
return _jsxs(Box, { sx: { p: 2 }, children: [_jsx(Typography.Title, { level: 4, children: "Test Case 1: Plain Object \u2192 Primitive Listeners" }), _jsxs(Typography.Paragraph, { children: ['Test setFieldValue("user", ', "{name, age}", ") v\u1EDBi deepTrigger=true"] }), _jsxs(Form, { formName: "testCase1", children: [_jsx(Form.Item, { name: "user", children: _jsx(Input, { placeholder: "User Object (JSON)", disabled: true }) }), _jsx(Form.Item, { name: "user.name", label: "Name", children: _jsx(Input, { placeholder: "Enter name" }) }), _jsx(Form.Item, { name: "user.age", label: "Age", children: _jsx(Input, { type: "number", placeholder: "Enter age" }) }), _jsxs(Box, { sx: { mt: 2, display: "flex", gap: 2 }, children: [_jsx(Button, { type: "primary", onClick: handleTestDeepTrigger, children: "Test Deep Trigger" }), _jsx(Button, { onClick: handleTestNormalSet, children: "Test Normal Set" })] })] })] });
|
|
14
|
+
}
|
|
15
|
+
var stdin_default = TestCase1_PlainObjectToPrimitives;
|
|
16
|
+
export {
|
|
17
|
+
stdin_default as default
|
|
18
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type Props = {};
|
|
2
|
+
/**
|
|
3
|
+
* Test Case 2: Plain Object → Array Listener (FormList) → Primitives
|
|
4
|
+
*
|
|
5
|
+
* Cấu trúc:
|
|
6
|
+
* - user.name (string)
|
|
7
|
+
* - user.items (array - FormList)
|
|
8
|
+
* - user.items.0.id (number)
|
|
9
|
+
* - user.items.0.title (string)
|
|
10
|
+
*
|
|
11
|
+
* Test: setFieldValue("user", {name: "John", items: [{id: 1, title: "Item 1"}]}, {deepTrigger: true})
|
|
12
|
+
* Kỳ vọng:
|
|
13
|
+
* - Trigger "user" listener
|
|
14
|
+
* - Trigger "user.name" listener
|
|
15
|
+
* - Trigger "user.items" onArrayChange
|
|
16
|
+
* - Trigger "user.items.0" listener
|
|
17
|
+
* - Trigger "user.items.0.id" listener
|
|
18
|
+
* - Trigger "user.items.0.title" listener
|
|
19
|
+
*/
|
|
20
|
+
declare function TestCase2_PlainObjectToFormList({}: Props): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export default TestCase2_PlainObjectToFormList;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
3
|
+
import { Button, Input, Typography } from "antd";
|
|
4
|
+
import FormList from "../../components/Form/FormList";
|
|
5
|
+
import Form from "../../providers/Form";
|
|
6
|
+
function TestCase2_PlainObjectToFormList({}) {
|
|
7
|
+
const [form] = Form.useForm("testCase2");
|
|
8
|
+
const handleTestDeepTrigger = () => {
|
|
9
|
+
form == null ? void 0 : form.setFieldValue("user", {
|
|
10
|
+
name: "John Doe",
|
|
11
|
+
items: [
|
|
12
|
+
{ id: 1, title: "Item 1" },
|
|
13
|
+
{ id: 2, title: "Item 2" }
|
|
14
|
+
]
|
|
15
|
+
}, { deepTrigger: true });
|
|
16
|
+
};
|
|
17
|
+
const handleTestNormalSet = () => {
|
|
18
|
+
form == null ? void 0 : form.setFieldValue("user", {
|
|
19
|
+
name: "Jane Doe",
|
|
20
|
+
items: [{ id: 3, title: "Item 3" }]
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
return _jsxs(Box, { sx: { p: 2 }, children: [_jsx(Typography.Title, { level: 4, children: "Test Case 2: Plain Object \u2192 FormList \u2192 Primitives" }), _jsxs(Typography.Paragraph, { children: ['Test setFieldValue("user", ', "{name, items: [...]}", ") v\u1EDBi nested FormList"] }), _jsxs(Form, { formName: "testCase2", children: [_jsx(Form.Item, { name: "user.name", label: "User Name", children: _jsx(Input, { placeholder: "Enter user name" }) }), _jsx(FormList, { name: "user.items", children: (fields, { add, remove }) => _jsxs(Box, { children: [fields.map((field, index) => _jsxs(Box, { sx: {
|
|
24
|
+
border: "1px solid #d9d9d9",
|
|
25
|
+
p: 2,
|
|
26
|
+
mb: 2,
|
|
27
|
+
borderRadius: 1
|
|
28
|
+
}, children: [_jsxs(Typography.Text, { strong: true, children: ["Item ", index + 1] }), _jsx(Form.Item, { name: `user.items.${index}.id`, label: "ID", children: _jsx(Input, { placeholder: "Item ID" }) }), _jsx(Form.Item, { name: `user.items.${index}.title`, label: "Title", children: _jsx(Input, { placeholder: "Item title" }) }), _jsx(Button, { danger: true, onClick: () => remove({ key: field.key }), children: "Remove" })] }, field.key)), _jsx(Button, { type: "dashed", onClick: () => add(), children: "Add Item" })] }) }), _jsxs(Box, { sx: { mt: 2, display: "flex", gap: 2 }, children: [_jsx(Button, { type: "primary", onClick: handleTestDeepTrigger, children: "Test Deep Trigger" }), _jsx(Button, { onClick: handleTestNormalSet, children: "Test Normal Set" })] })] })] });
|
|
29
|
+
}
|
|
30
|
+
var stdin_default = TestCase2_PlainObjectToFormList;
|
|
31
|
+
export {
|
|
32
|
+
stdin_default as default
|
|
33
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type Props = {};
|
|
2
|
+
/**
|
|
3
|
+
* Test Case 3: Array Non-Listener → Primitives
|
|
4
|
+
*
|
|
5
|
+
* Cấu trúc:
|
|
6
|
+
* - data (array - KHÔNG phải FormList, chỉ là field bình thường)
|
|
7
|
+
* - data.0.name (string)
|
|
8
|
+
* - data.0.value (number)
|
|
9
|
+
*
|
|
10
|
+
* Test: setFieldValue("data", [{name: "A", value: 1}, {name: "B", value: 2}], {deepTrigger: true})
|
|
11
|
+
* Kỳ vọng:
|
|
12
|
+
* - Set data array vào store
|
|
13
|
+
* - Trigger "data.0" listener (nếu có)
|
|
14
|
+
* - Trigger "data.0.name" listener
|
|
15
|
+
* - Trigger "data.0.value" listener
|
|
16
|
+
* - Trigger "data.1" listener (nếu có)
|
|
17
|
+
* - Trigger "data.1.name" listener
|
|
18
|
+
* - Trigger "data.1.value" listener
|
|
19
|
+
*/
|
|
20
|
+
declare function TestCase3_ArrayNonListenerToPrimitives({}: Props): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export default TestCase3_ArrayNonListenerToPrimitives;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
3
|
+
import { Button, Input, Typography } from "antd";
|
|
4
|
+
import Form from "../../providers/Form";
|
|
5
|
+
function TestCase3_ArrayNonListenerToPrimitives({}) {
|
|
6
|
+
const [form] = Form.useForm("testCase3");
|
|
7
|
+
const handleTestDeepTrigger = () => {
|
|
8
|
+
form == null ? void 0 : form.setFieldValue("data", [
|
|
9
|
+
{ name: "Item A", value: 100 },
|
|
10
|
+
{ name: "Item B", value: 200 }
|
|
11
|
+
], { deepTrigger: true });
|
|
12
|
+
};
|
|
13
|
+
const handleTestRemoveItems = () => {
|
|
14
|
+
form == null ? void 0 : form.setFieldValue("data", [{ name: "Item A", value: 100 }], {
|
|
15
|
+
deepTrigger: true
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const handleTestNormalSet = () => {
|
|
19
|
+
form == null ? void 0 : form.setFieldValue("data", [{ name: "Item C", value: 300 }]);
|
|
20
|
+
};
|
|
21
|
+
return _jsxs(Box, { sx: { p: 2 }, children: [_jsx(Typography.Title, { level: 4, children: "Test Case 3: Array Non-Listener \u2192 Primitives" }), _jsxs(Typography.Paragraph, { children: ['Test setFieldValue("data", ', "[{name, value}, ...]", ") v\u1EDBi array kh\xF4ng ph\u1EA3i FormList"] }), _jsxs(Form, { formName: "testCase3", children: [_jsxs(Box, { sx: { border: "1px solid #d9d9d9", p: 2, mb: 2, borderRadius: 1 }, children: [_jsx(Typography.Text, { strong: true, children: "Item 0" }), _jsx(Form.Item, { name: "data.0.name", label: "Name", children: _jsx(Input, { placeholder: "Item 0 name" }) }), _jsx(Form.Item, { name: "data.0.value", label: "Value", children: _jsx(Input, { type: "number", placeholder: "Item 0 value" }) })] }), _jsxs(Box, { sx: { border: "1px solid #d9d9d9", p: 2, mb: 2, borderRadius: 1 }, children: [_jsx(Typography.Text, { strong: true, children: "Item 1" }), _jsx(Form.Item, { name: "data.1.name", label: "Name", children: _jsx(Input, { placeholder: "Item 1 name" }) }), _jsx(Form.Item, { name: "data.1.value", label: "Value", children: _jsx(Input, { type: "number", placeholder: "Item 1 value" }) })] }), _jsxs(Box, { sx: { mt: 2, display: "flex", gap: 2 }, children: [_jsx(Button, { type: "primary", onClick: handleTestDeepTrigger, children: "Test Deep Trigger (2 items)" }), _jsx(Button, { onClick: handleTestRemoveItems, children: "Test Remove Items (1 item)" }), _jsx(Button, { onClick: handleTestNormalSet, children: "Test Normal Set" })] })] })] });
|
|
22
|
+
}
|
|
23
|
+
var stdin_default = TestCase3_ArrayNonListenerToPrimitives;
|
|
24
|
+
export {
|
|
25
|
+
stdin_default as default
|
|
26
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type Props = {};
|
|
2
|
+
/**
|
|
3
|
+
* Test Case 4: Plain Object with Removed Fields (Edge Case)
|
|
4
|
+
*
|
|
5
|
+
* Cấu trúc ban đầu:
|
|
6
|
+
* - profile.name (string)
|
|
7
|
+
* - profile.city (string)
|
|
8
|
+
* - profile.country (string)
|
|
9
|
+
*
|
|
10
|
+
* Test:
|
|
11
|
+
* 1. Set initial: {name: "John", city: "NY", country: "USA"}
|
|
12
|
+
* 2. Set removed: {name: "John"} (city và country bị xóa)
|
|
13
|
+
*
|
|
14
|
+
* Kỳ vọng:
|
|
15
|
+
* - Trigger "profile.name" với "John"
|
|
16
|
+
* - Trigger "profile.city" với undefined (cleanup)
|
|
17
|
+
* - Trigger "profile.country" với undefined (cleanup)
|
|
18
|
+
*/
|
|
19
|
+
declare function TestCase4_PlainObjectRemovedFields({}: Props): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export default TestCase4_PlainObjectRemovedFields;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
3
|
+
import { Button, Input, Typography } from "antd";
|
|
4
|
+
import Form from "../../providers/Form";
|
|
5
|
+
function TestCase4_PlainObjectRemovedFields({}) {
|
|
6
|
+
const [form] = Form.useForm("testCase4");
|
|
7
|
+
const handleSetInitial = () => {
|
|
8
|
+
form == null ? void 0 : form.setFieldValue("profile", {
|
|
9
|
+
name: "John Doe",
|
|
10
|
+
city: "New York",
|
|
11
|
+
country: "USA"
|
|
12
|
+
}, { deepTrigger: true });
|
|
13
|
+
};
|
|
14
|
+
const handleRemoveFields = () => {
|
|
15
|
+
form == null ? void 0 : form.setFieldValue("profile", {
|
|
16
|
+
name: "John Doe"
|
|
17
|
+
// city and country removed!
|
|
18
|
+
}, { deepTrigger: true });
|
|
19
|
+
};
|
|
20
|
+
const handleRestoreFields = () => {
|
|
21
|
+
form == null ? void 0 : form.setFieldValue("profile", {
|
|
22
|
+
name: "Jane Doe",
|
|
23
|
+
city: "Los Angeles",
|
|
24
|
+
country: "USA"
|
|
25
|
+
}, { deepTrigger: true });
|
|
26
|
+
};
|
|
27
|
+
return _jsxs(Box, { sx: { p: 2 }, children: [_jsx(Typography.Title, { level: 4, children: "Test Case 4: Plain Object - Removed Fields" }), _jsx(Typography.Paragraph, { children: "Test edge case: khi object fields b\u1ECB x\xF3a, listener ph\u1EA3i \u0111\u01B0\u1EE3c trigger v\u1EDBi undefined" }), _jsxs(Form, { formName: "testCase4", children: [_jsx(Form.Item, { name: "profile.name", label: "Name", children: _jsx(Input, { placeholder: "Enter name" }) }), _jsx(Form.Item, { name: "profile.city", label: "City", children: _jsx(Input, { placeholder: "Enter city" }) }), _jsx(Form.Item, { name: "profile.country", label: "Country", children: _jsx(Input, { placeholder: "Enter country" }) }), _jsxs(Box, { sx: { mt: 2, display: "flex", gap: 2, flexDirection: "column" }, children: [_jsx(Button, { type: "primary", onClick: handleSetInitial, children: "1. Set Initial (All Fields)" }), _jsx(Button, { danger: true, onClick: handleRemoveFields, children: "2. Remove Fields (city, country)" }), _jsx(Button, { onClick: handleRestoreFields, children: "3. Restore Fields" })] }), _jsxs(Box, { sx: { mt: 2, p: 2, bgcolor: "#f0f0f0", borderRadius: 1 }, children: [_jsx(Typography.Text, { strong: true, children: "Expected Behavior:" }), _jsx(Typography.Paragraph, { children: 'Khi click "Remove Fields", city v\xE0 country listeners ph\u1EA3i nh\u1EADn undefined' })] })] })] });
|
|
28
|
+
}
|
|
29
|
+
var stdin_default = TestCase4_PlainObjectRemovedFields;
|
|
30
|
+
export {
|
|
31
|
+
stdin_default as default
|
|
32
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
type Props = {};
|
|
2
|
+
/**
|
|
3
|
+
* Test Case 5: Array Listener (FormList) with Removed Items
|
|
4
|
+
*
|
|
5
|
+
* Cấu trúc:
|
|
6
|
+
* - items (FormList)
|
|
7
|
+
* - items.0.name (string)
|
|
8
|
+
* - items.1.name (string)
|
|
9
|
+
* - items.2.name (string)
|
|
10
|
+
*
|
|
11
|
+
* Test:
|
|
12
|
+
* 1. Set initial: [{name: "A"}, {name: "B"}, {name: "C"}]
|
|
13
|
+
* 2. Set removed: [{name: "A"}] (items 1 và 2 bị xóa)
|
|
14
|
+
*
|
|
15
|
+
* Kỳ vọng:
|
|
16
|
+
* - onArrayChange được gọi với array mới
|
|
17
|
+
* - Trigger "items.0.name" với "A"
|
|
18
|
+
* - Trigger "items.1" với undefined (cleanup)
|
|
19
|
+
* - Trigger "items.2" với undefined (cleanup)
|
|
20
|
+
*/
|
|
21
|
+
declare function TestCase5_FormListRemovedItems({}: Props): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export default TestCase5_FormListRemovedItems;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
3
|
+
import { Button, Input, Typography } from "antd";
|
|
4
|
+
import FormList from "../../components/Form/FormList";
|
|
5
|
+
import Form from "../../providers/Form";
|
|
6
|
+
function TestCase5_FormListRemovedItems({}) {
|
|
7
|
+
const [form] = Form.useForm("testCase5");
|
|
8
|
+
const handleSetInitial = () => {
|
|
9
|
+
form == null ? void 0 : form.setFieldValue("items", [{ name: "Item A" }, { name: "Item B" }, { name: "Item C" }], { deepTrigger: true });
|
|
10
|
+
};
|
|
11
|
+
const handleRemoveItems = () => {
|
|
12
|
+
form == null ? void 0 : form.setFieldValue("items", [{ name: "Item A" }], { deepTrigger: true });
|
|
13
|
+
};
|
|
14
|
+
const handleRestoreItems = () => {
|
|
15
|
+
form == null ? void 0 : form.setFieldValue("items", [{ name: "Item A" }, { name: "Item B" }], {
|
|
16
|
+
deepTrigger: true
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
return _jsxs(Box, { sx: { p: 2 }, children: [_jsx(Typography.Title, { level: 4, children: "Test Case 5: FormList - Removed Items" }), _jsx(Typography.Paragraph, { children: "Test edge case: khi FormList items b\u1ECB x\xF3a, listeners ph\u1EA3i \u0111\u01B0\u1EE3c trigger v\u1EDBi undefined" }), _jsxs(Form, { formName: "testCase5", children: [_jsx(FormList, { name: "items", children: (fields, { add, remove }) => _jsxs(Box, { children: [fields.map((field, index) => _jsxs(Box, { sx: {
|
|
20
|
+
border: "1px solid #d9d9d9",
|
|
21
|
+
p: 2,
|
|
22
|
+
mb: 2,
|
|
23
|
+
borderRadius: 1
|
|
24
|
+
}, children: [_jsxs(Typography.Text, { strong: true, children: ["Item ", index + 1] }), _jsx(Form.Item, { name: `items.${index}.name`, label: "Name", children: _jsx(Input, { placeholder: `Item ${index + 1} name` }) }), _jsx(Button, { danger: true, onClick: () => remove({ key: field.key }), children: "Remove" })] }, field.key)), _jsx(Button, { type: "dashed", onClick: () => add(), children: "Add Item" })] }) }), _jsxs(Box, { sx: { mt: 2, display: "flex", gap: 2, flexDirection: "column" }, children: [_jsx(Button, { type: "primary", onClick: handleSetInitial, children: "1. Set Initial (3 Items)" }), _jsx(Button, { danger: true, onClick: handleRemoveItems, children: "2. Remove Items (Keep 1)" }), _jsx(Button, { onClick: handleRestoreItems, children: "3. Restore Items (2 Items)" })] }), _jsxs(Box, { sx: { mt: 2, p: 2, bgcolor: "#f0f0f0", borderRadius: 1 }, children: [_jsx(Typography.Text, { strong: true, children: "Expected Behavior:" }), _jsx(Typography.Paragraph, { children: 'Khi click "Remove Items", items.1 v\xE0 items.2 listeners ph\u1EA3i nh\u1EADn undefined' })] })] })] });
|
|
25
|
+
}
|
|
26
|
+
var stdin_default = TestCase5_FormListRemovedItems;
|
|
27
|
+
export {
|
|
28
|
+
stdin_default as default
|
|
29
|
+
};
|