@teamnovu/kit-vue-forms 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/FormFieldWrapper.vue.d.ts +1 -1
- package/dist/composables/useField.d.ts +5 -2
- package/dist/composables/useFieldRegistry.d.ts +13 -4
- package/dist/composables/useFormData.d.ts +5 -0
- package/dist/index.js +370 -324
- package/dist/types/form.d.ts +3 -1
- package/docs/reference.md +0 -2
- package/package.json +1 -1
- package/src/components/FormFieldWrapper.vue +8 -0
- package/src/composables/useField.ts +9 -3
- package/src/composables/useFieldRegistry.ts +80 -14
- package/src/composables/useForm.ts +53 -10
- package/src/composables/useFormData.ts +1 -1
- package/src/composables/useValidation.ts +1 -1
- package/src/types/form.ts +23 -8
- package/src/utils/path.ts +7 -1
- package/tests/subform.test.ts +17 -0
- package/tests/useField.test.ts +17 -0
- package/tests/useForm.test.ts +313 -201
- package/tests/useValidation.test.ts +73 -1
package/tests/useForm.test.ts
CHANGED
|
@@ -1,359 +1,471 @@
|
|
|
1
|
-
import { describe, expect, it } from
|
|
2
|
-
import { effectScope, isReactive, nextTick, reactive, ref } from
|
|
3
|
-
import { z } from
|
|
4
|
-
import { useForm } from
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { effectScope, isReactive, nextTick, reactive, ref } from "vue";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { useForm } from "../src/composables/useForm";
|
|
5
5
|
|
|
6
|
-
const scope = effectScope()
|
|
6
|
+
const scope = effectScope();
|
|
7
7
|
|
|
8
|
-
describe(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
})
|
|
12
|
-
it('should initialize form with initial data', () => {
|
|
8
|
+
describe("useForm", () => {
|
|
9
|
+
it("should initialize form with initial data", () => {
|
|
13
10
|
const initialData = {
|
|
14
|
-
name:
|
|
11
|
+
name: "John",
|
|
15
12
|
age: 30,
|
|
16
|
-
}
|
|
17
|
-
const form = useForm({ initialData })
|
|
13
|
+
};
|
|
14
|
+
const form = useForm({ initialData });
|
|
18
15
|
|
|
19
|
-
expect(form.data.value).toEqual(initialData)
|
|
20
|
-
expect(form.initialData.value).toEqual(initialData)
|
|
21
|
-
})
|
|
16
|
+
expect(form.data.value).toEqual(initialData);
|
|
17
|
+
expect(form.initialData.value).toEqual(initialData);
|
|
18
|
+
});
|
|
22
19
|
|
|
23
|
-
it(
|
|
20
|
+
it("should initialize form with reactive initial data", async () => {
|
|
24
21
|
const initialData = ref({
|
|
25
|
-
name:
|
|
22
|
+
name: "John",
|
|
26
23
|
age: 30,
|
|
27
|
-
})
|
|
28
|
-
const form = useForm({ initialData })
|
|
24
|
+
});
|
|
25
|
+
const form = useForm({ initialData });
|
|
29
26
|
|
|
30
27
|
expect(form.data.value).toEqual({
|
|
31
|
-
name:
|
|
28
|
+
name: "John",
|
|
32
29
|
age: 30,
|
|
33
|
-
})
|
|
30
|
+
});
|
|
34
31
|
|
|
35
32
|
// Update reactive initial data
|
|
36
33
|
initialData.value = {
|
|
37
|
-
name:
|
|
34
|
+
name: "Jane",
|
|
38
35
|
age: 25,
|
|
39
|
-
}
|
|
40
|
-
await nextTick()
|
|
36
|
+
};
|
|
37
|
+
await nextTick();
|
|
41
38
|
|
|
42
39
|
expect(form.initialData.value).toEqual({
|
|
43
|
-
name:
|
|
40
|
+
name: "Jane",
|
|
44
41
|
age: 25,
|
|
45
|
-
})
|
|
46
|
-
})
|
|
42
|
+
});
|
|
43
|
+
});
|
|
47
44
|
|
|
48
|
-
it(
|
|
45
|
+
it("should reinitialize form with new initial data", async () => {
|
|
49
46
|
const initialData = ref({
|
|
50
|
-
name:
|
|
47
|
+
name: "John",
|
|
51
48
|
age: 30,
|
|
52
|
-
})
|
|
53
|
-
const form = useForm({ initialData })
|
|
49
|
+
});
|
|
50
|
+
const form = useForm({ initialData });
|
|
54
51
|
|
|
55
52
|
expect(form.data.value).toEqual({
|
|
56
|
-
name:
|
|
53
|
+
name: "John",
|
|
57
54
|
age: 30,
|
|
58
|
-
})
|
|
55
|
+
});
|
|
59
56
|
|
|
60
57
|
// Update reactive initial data
|
|
61
58
|
initialData.value = {
|
|
62
|
-
name:
|
|
59
|
+
name: "Jane",
|
|
63
60
|
age: 25,
|
|
64
|
-
}
|
|
65
|
-
await nextTick()
|
|
61
|
+
};
|
|
62
|
+
await nextTick();
|
|
66
63
|
|
|
67
64
|
expect(form.data.value).toEqual({
|
|
68
|
-
name:
|
|
65
|
+
name: "Jane",
|
|
69
66
|
age: 25,
|
|
70
|
-
})
|
|
71
|
-
})
|
|
67
|
+
});
|
|
68
|
+
});
|
|
72
69
|
|
|
73
|
-
it(
|
|
74
|
-
const form = useForm({ initialData: { name:
|
|
70
|
+
it("should have initial state values", () => {
|
|
71
|
+
const form = useForm({ initialData: { name: "John" } });
|
|
75
72
|
|
|
76
|
-
expect(form.isDirty.value).toBe(false)
|
|
77
|
-
expect(form.isTouched.value).toBe(false)
|
|
78
|
-
expect(form.isValid.value).toBe(true)
|
|
79
|
-
expect(form.isValidated.value).toBe(false)
|
|
80
|
-
})
|
|
73
|
+
expect(form.isDirty.value).toBe(false);
|
|
74
|
+
expect(form.isTouched.value).toBe(false);
|
|
75
|
+
expect(form.isValid.value).toBe(true);
|
|
76
|
+
expect(form.isValidated.value).toBe(false);
|
|
77
|
+
});
|
|
81
78
|
|
|
82
|
-
it(
|
|
79
|
+
it("should define fields and auto-register them", () => {
|
|
83
80
|
const form = useForm({
|
|
84
81
|
initialData: {
|
|
85
|
-
name:
|
|
86
|
-
email:
|
|
82
|
+
name: "John",
|
|
83
|
+
email: "john@example.com",
|
|
87
84
|
},
|
|
88
|
-
})
|
|
85
|
+
});
|
|
89
86
|
|
|
90
|
-
const nameField = form.defineField({ path:
|
|
91
|
-
const emailField = form.defineField({ path:
|
|
87
|
+
const nameField = form.defineField({ path: "name" });
|
|
88
|
+
const emailField = form.defineField({ path: "email" });
|
|
92
89
|
|
|
93
|
-
expect(nameField.path.value).toBe(
|
|
94
|
-
expect(emailField.path.value).toBe(
|
|
95
|
-
expect(form.fields.value.length).toBe(2)
|
|
96
|
-
})
|
|
90
|
+
expect(nameField.path.value).toBe("name");
|
|
91
|
+
expect(emailField.path.value).toBe("email");
|
|
92
|
+
expect(form.fields.value.length).toBe(2);
|
|
93
|
+
});
|
|
97
94
|
|
|
98
|
-
it(
|
|
95
|
+
it("should get registered fields", () => {
|
|
99
96
|
const form = useForm({
|
|
100
97
|
initialData: {
|
|
101
|
-
name:
|
|
102
|
-
email:
|
|
98
|
+
name: "John",
|
|
99
|
+
email: "john@example.com",
|
|
103
100
|
},
|
|
104
|
-
})
|
|
101
|
+
});
|
|
105
102
|
|
|
106
|
-
const nameField = form.defineField({ path:
|
|
107
|
-
form.defineField({ path:
|
|
103
|
+
const nameField = form.defineField({ path: "name" });
|
|
104
|
+
form.defineField({ path: "email" });
|
|
108
105
|
|
|
109
|
-
const retrievedField = form.getField(
|
|
110
|
-
expect(retrievedField?.path.value).toBe(
|
|
111
|
-
expect(retrievedField).toBe(nameField)
|
|
112
|
-
})
|
|
106
|
+
const retrievedField = form.getField("name");
|
|
107
|
+
expect(retrievedField?.path.value).toBe("name");
|
|
108
|
+
expect(retrievedField).toBe(nameField);
|
|
109
|
+
});
|
|
113
110
|
|
|
114
|
-
it(
|
|
111
|
+
it("should handle nested object initial data", () => {
|
|
115
112
|
const initialData = {
|
|
116
113
|
user: {
|
|
117
|
-
name:
|
|
114
|
+
name: "John",
|
|
118
115
|
address: {
|
|
119
|
-
street:
|
|
120
|
-
city:
|
|
116
|
+
street: "123 Main St",
|
|
117
|
+
city: "New York",
|
|
121
118
|
},
|
|
122
119
|
},
|
|
123
|
-
}
|
|
124
|
-
const form = useForm({ initialData })
|
|
120
|
+
};
|
|
121
|
+
const form = useForm({ initialData });
|
|
125
122
|
|
|
126
|
-
expect(form.data.value).toEqual(initialData)
|
|
127
|
-
expect(form.initialData.value).toEqual(initialData)
|
|
128
|
-
})
|
|
123
|
+
expect(form.data.value).toEqual(initialData);
|
|
124
|
+
expect(form.initialData.value).toEqual(initialData);
|
|
125
|
+
});
|
|
129
126
|
|
|
130
|
-
it(
|
|
127
|
+
it("should validate with schema", async () => {
|
|
131
128
|
const schema = z.object({
|
|
132
129
|
name: z.string().min(2),
|
|
133
130
|
age: z.number().min(18),
|
|
134
|
-
})
|
|
131
|
+
});
|
|
135
132
|
|
|
136
133
|
const form = useForm({
|
|
137
134
|
initialData: {
|
|
138
|
-
name:
|
|
135
|
+
name: "A",
|
|
139
136
|
age: 16,
|
|
140
137
|
},
|
|
141
138
|
schema,
|
|
142
|
-
})
|
|
139
|
+
});
|
|
143
140
|
|
|
144
|
-
const result = await form.validateForm()
|
|
141
|
+
const result = await form.validateForm();
|
|
145
142
|
|
|
146
|
-
expect(result.isValid).toBe(false)
|
|
147
|
-
expect(form.isValidated.value).toBe(true)
|
|
148
|
-
expect(form.errors.value.propertyErrors.name).toBeDefined()
|
|
149
|
-
expect(form.errors.value.propertyErrors.age).toBeDefined()
|
|
150
|
-
})
|
|
143
|
+
expect(result.isValid).toBe(false);
|
|
144
|
+
expect(form.isValidated.value).toBe(true);
|
|
145
|
+
expect(form.errors.value.propertyErrors.name).toBeDefined();
|
|
146
|
+
expect(form.errors.value.propertyErrors.age).toBeDefined();
|
|
147
|
+
});
|
|
151
148
|
|
|
152
|
-
it(
|
|
149
|
+
it("should validate with custom function", async () => {
|
|
153
150
|
const validateFn = async (data: { name: string }) => {
|
|
154
151
|
const errors = {
|
|
155
152
|
general: [],
|
|
156
153
|
propertyErrors: {} as Record<string, string[]>,
|
|
157
|
-
}
|
|
154
|
+
};
|
|
158
155
|
|
|
159
156
|
if (data.name.length < 2) {
|
|
160
|
-
errors.propertyErrors.name = [
|
|
157
|
+
errors.propertyErrors.name = ["Name too short"];
|
|
161
158
|
}
|
|
162
159
|
|
|
163
160
|
return {
|
|
164
161
|
isValid: Object.keys(errors.propertyErrors).length === 0,
|
|
165
162
|
errors,
|
|
166
|
-
}
|
|
167
|
-
}
|
|
163
|
+
};
|
|
164
|
+
};
|
|
168
165
|
|
|
169
166
|
const form = useForm({
|
|
170
|
-
initialData: { name:
|
|
167
|
+
initialData: { name: "A" },
|
|
171
168
|
validateFn,
|
|
172
|
-
})
|
|
169
|
+
});
|
|
173
170
|
|
|
174
|
-
const result = await form.validateForm()
|
|
171
|
+
const result = await form.validateForm();
|
|
175
172
|
|
|
176
|
-
expect(result.isValid).toBe(false)
|
|
177
|
-
expect(result.errors.propertyErrors.name).toEqual([
|
|
178
|
-
})
|
|
173
|
+
expect(result.isValid).toBe(false);
|
|
174
|
+
expect(result.errors.propertyErrors.name).toEqual(["Name too short"]);
|
|
175
|
+
});
|
|
179
176
|
|
|
180
|
-
it(
|
|
177
|
+
it("should pass validation with valid data", async () => {
|
|
181
178
|
const schema = z.object({
|
|
182
179
|
name: z.string().min(2),
|
|
183
180
|
age: z.number().min(18),
|
|
184
|
-
})
|
|
181
|
+
});
|
|
185
182
|
|
|
186
183
|
const form = useForm({
|
|
187
184
|
initialData: {
|
|
188
|
-
name:
|
|
185
|
+
name: "John",
|
|
189
186
|
age: 30,
|
|
190
187
|
},
|
|
191
188
|
schema,
|
|
192
|
-
})
|
|
189
|
+
});
|
|
193
190
|
|
|
194
|
-
const result = await form.validateForm()
|
|
191
|
+
const result = await form.validateForm();
|
|
195
192
|
|
|
196
|
-
expect(result.isValid).toBe(true)
|
|
197
|
-
expect(form.isValidated.value).toBe(true)
|
|
198
|
-
expect(form.errors.value.general).toEqual([])
|
|
199
|
-
expect(form.errors.value.propertyErrors).toEqual({})
|
|
200
|
-
})
|
|
193
|
+
expect(result.isValid).toBe(true);
|
|
194
|
+
expect(form.isValidated.value).toBe(true);
|
|
195
|
+
expect(form.errors.value.general).toEqual([]);
|
|
196
|
+
expect(form.errors.value.propertyErrors).toEqual({});
|
|
197
|
+
});
|
|
201
198
|
|
|
202
|
-
it(
|
|
203
|
-
const schema = z.array(z.string())
|
|
199
|
+
it("can handle arrays on top level", async () => {
|
|
200
|
+
const schema = z.array(z.string());
|
|
204
201
|
|
|
205
202
|
const form = useForm({
|
|
206
|
-
initialData: [
|
|
203
|
+
initialData: ["item1", "item2"],
|
|
207
204
|
schema,
|
|
208
|
-
})
|
|
205
|
+
});
|
|
209
206
|
|
|
210
|
-
const result = await form.validateForm()
|
|
207
|
+
const result = await form.validateForm();
|
|
211
208
|
|
|
212
|
-
expect(result.isValid).toBe(true)
|
|
213
|
-
expect(form.isValidated.value).toBe(true)
|
|
214
|
-
expect(form.errors.value.general).toEqual([])
|
|
215
|
-
expect(form.errors.value.propertyErrors).toEqual({})
|
|
209
|
+
expect(result.isValid).toBe(true);
|
|
210
|
+
expect(form.isValidated.value).toBe(true);
|
|
211
|
+
expect(form.errors.value.general).toEqual([]);
|
|
212
|
+
expect(form.errors.value.propertyErrors).toEqual({});
|
|
216
213
|
|
|
217
|
-
const rootField = form.defineField({ path:
|
|
218
|
-
const itemField = form.defineField({ path:
|
|
214
|
+
const rootField = form.defineField({ path: "" });
|
|
215
|
+
const itemField = form.defineField({ path: "1" });
|
|
219
216
|
|
|
220
|
-
expect(rootField.data.value).toEqual([
|
|
221
|
-
expect(itemField.data.value).toBe(
|
|
222
|
-
})
|
|
217
|
+
expect(rootField.data.value).toEqual(["item1", "item2"]);
|
|
218
|
+
expect(itemField.data.value).toBe("item2");
|
|
219
|
+
});
|
|
223
220
|
|
|
224
|
-
it(
|
|
221
|
+
it("can handle late initialized fields", async () => {
|
|
225
222
|
const form = useForm({
|
|
226
223
|
initialData: {
|
|
227
|
-
name:
|
|
224
|
+
name: "John",
|
|
228
225
|
age: 30,
|
|
229
226
|
},
|
|
230
|
-
})
|
|
227
|
+
});
|
|
231
228
|
|
|
232
229
|
// No fields defined yet
|
|
233
|
-
expect(form.fields.value).toEqual([])
|
|
234
|
-
expect(form.isDirty.value).toBe(false)
|
|
230
|
+
expect(form.fields.value).toEqual([]);
|
|
231
|
+
expect(form.isDirty.value).toBe(false);
|
|
235
232
|
|
|
236
|
-
const nameField = form.defineField({ path:
|
|
233
|
+
const nameField = form.defineField({ path: "name" });
|
|
237
234
|
|
|
238
|
-
expect(form.fields.value.length).toBe(1)
|
|
239
|
-
expect(form.isDirty.value).toBe(false)
|
|
235
|
+
expect(form.fields.value.length).toBe(1);
|
|
236
|
+
expect(form.isDirty.value).toBe(false);
|
|
240
237
|
|
|
241
|
-
nameField.setData(
|
|
238
|
+
nameField.setData("Bob");
|
|
242
239
|
|
|
243
|
-
expect(form.isDirty.value).toBe(true)
|
|
244
|
-
})
|
|
240
|
+
expect(form.isDirty.value).toBe(true);
|
|
241
|
+
});
|
|
245
242
|
|
|
246
|
-
it(
|
|
243
|
+
it("fields can be made reactive", async () => {
|
|
247
244
|
const form = useForm({
|
|
248
245
|
initialData: {
|
|
249
|
-
name:
|
|
246
|
+
name: "John",
|
|
250
247
|
age: 30,
|
|
251
248
|
},
|
|
252
|
-
})
|
|
249
|
+
});
|
|
253
250
|
|
|
254
|
-
const nameField = form.defineField({ path:
|
|
251
|
+
const nameField = form.defineField({ path: "name" });
|
|
255
252
|
|
|
256
|
-
expect(isReactive(reactive(nameField))).toBe(true)
|
|
257
|
-
})
|
|
253
|
+
expect(isReactive(reactive(nameField))).toBe(true);
|
|
254
|
+
});
|
|
258
255
|
|
|
259
|
-
it(
|
|
256
|
+
it("fields should only be removed when all references are gone", async () => {
|
|
260
257
|
const form = useForm({
|
|
261
258
|
initialData: {
|
|
262
|
-
name:
|
|
259
|
+
name: "John",
|
|
263
260
|
age: 30,
|
|
264
261
|
},
|
|
265
|
-
})
|
|
262
|
+
});
|
|
266
263
|
|
|
267
|
-
expect(form.fields.value).toEqual([])
|
|
264
|
+
expect(form.fields.value).toEqual([]);
|
|
268
265
|
|
|
269
|
-
const scope1 = effectScope()
|
|
266
|
+
const scope1 = effectScope();
|
|
270
267
|
|
|
271
268
|
scope1.run(() => {
|
|
272
|
-
form.defineField({ path:
|
|
273
|
-
})
|
|
269
|
+
form.defineField({ path: "name" });
|
|
270
|
+
});
|
|
274
271
|
|
|
275
|
-
expect(form.fields.value.length).toBe(1)
|
|
272
|
+
expect(form.fields.value.length).toBe(1);
|
|
276
273
|
|
|
277
|
-
const scope2 = effectScope()
|
|
274
|
+
const scope2 = effectScope();
|
|
278
275
|
|
|
279
276
|
scope2.run(() => {
|
|
280
|
-
form.defineField({ path:
|
|
281
|
-
})
|
|
277
|
+
form.defineField({ path: "name" });
|
|
278
|
+
});
|
|
282
279
|
|
|
283
|
-
expect(form.fields.value.length).toBe(1)
|
|
280
|
+
expect(form.fields.value.length).toBe(1);
|
|
284
281
|
|
|
285
|
-
scope1.stop()
|
|
282
|
+
scope1.stop();
|
|
286
283
|
|
|
287
|
-
expect(form.fields.value.length).toBe(1)
|
|
284
|
+
expect(form.fields.value.length).toBe(1);
|
|
288
285
|
|
|
289
|
-
scope2.stop()
|
|
286
|
+
scope2.stop();
|
|
290
287
|
|
|
291
|
-
expect(form.fields.value.length).toBe(0)
|
|
292
|
-
})
|
|
288
|
+
expect(form.fields.value.length).toBe(0);
|
|
289
|
+
});
|
|
293
290
|
|
|
294
|
-
it(
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
291
|
+
it(
|
|
292
|
+
"it should take over the new initial data from the form",
|
|
293
|
+
{ timeout: 500 },
|
|
294
|
+
async () => {
|
|
295
|
+
const initialData = ref({
|
|
296
|
+
name: "foo",
|
|
297
|
+
});
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
const form = useForm({
|
|
300
|
+
initialData,
|
|
301
|
+
});
|
|
302
302
|
|
|
303
|
-
|
|
303
|
+
const nameField = form.getField("name");
|
|
304
304
|
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
expect(form.isDirty.value).toBe(false);
|
|
306
|
+
expect(nameField.dirty.value).toBe(false);
|
|
307
307
|
|
|
308
|
-
|
|
308
|
+
nameField.setData("modified");
|
|
309
309
|
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
expect(form.isDirty.value).toBe(true);
|
|
311
|
+
expect(nameField.dirty.value).toBe(true);
|
|
312
312
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
313
|
+
initialData.value = {
|
|
314
|
+
name: "bar",
|
|
315
|
+
};
|
|
316
316
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
317
|
+
expect(form.initialData.value.name).toBe("bar");
|
|
318
|
+
expect(nameField.initialValue.value).toBe("bar");
|
|
319
|
+
expect(nameField.data.value).toBe("bar");
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
nameField.setInitialData("another");
|
|
322
322
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
expect(nameField.initialValue.value).toBe("another");
|
|
324
|
+
expect(nameField.data.value).toBe("another");
|
|
325
|
+
},
|
|
326
|
+
);
|
|
326
327
|
|
|
327
|
-
it(
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
328
|
+
it(
|
|
329
|
+
"it should take over the new initial data from the form after setting initial data on field",
|
|
330
|
+
{ timeout: 500 },
|
|
331
|
+
async () => {
|
|
332
|
+
const initialData = ref({
|
|
333
|
+
name: null as null | number,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const form = useForm({
|
|
337
|
+
initialData,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const nameField = form.getField("name");
|
|
341
|
+
|
|
342
|
+
expect(form.isDirty.value).toBe(false);
|
|
343
|
+
expect(nameField.dirty.value).toBe(false);
|
|
344
|
+
|
|
345
|
+
nameField.setInitialData(0);
|
|
331
346
|
|
|
347
|
+
expect(form.isDirty.value).toBe(false);
|
|
348
|
+
expect(nameField.dirty.value).toBe(false);
|
|
349
|
+
|
|
350
|
+
initialData.value = {
|
|
351
|
+
name: null,
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
expect(form.initialData.value.name).toBe(null);
|
|
355
|
+
expect(nameField.initialValue.value).toBe(null);
|
|
356
|
+
expect(nameField.data.value).toBe(null);
|
|
357
|
+
|
|
358
|
+
nameField.setInitialData(23);
|
|
359
|
+
|
|
360
|
+
expect(nameField.initialValue.value).toBe(23);
|
|
361
|
+
expect(nameField.data.value).toBe(23);
|
|
362
|
+
},
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
it("it should keep values on unmount if keepValuesOnUnmount is true (default)", async () => {
|
|
332
366
|
const form = useForm({
|
|
333
|
-
initialData
|
|
334
|
-
|
|
367
|
+
initialData: {
|
|
368
|
+
name: "A",
|
|
369
|
+
},
|
|
370
|
+
});
|
|
335
371
|
|
|
336
|
-
|
|
372
|
+
effectScope().run(() => {
|
|
373
|
+
const nameField = form.defineField({ path: "name" });
|
|
337
374
|
|
|
338
|
-
|
|
339
|
-
|
|
375
|
+
expect(form.fields.value.length).toBe(1);
|
|
376
|
+
expect(nameField.data.value).toBe("A");
|
|
340
377
|
|
|
341
|
-
|
|
378
|
+
nameField.setData("Modified");
|
|
379
|
+
});
|
|
342
380
|
|
|
343
|
-
expect(form.
|
|
344
|
-
|
|
381
|
+
expect(form.data.value.name).toBe("Modified");
|
|
382
|
+
});
|
|
345
383
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
384
|
+
it("it should NOT keep values on unmount if keepValuesOnUnmount is false", async () => {
|
|
385
|
+
const form = useForm({
|
|
386
|
+
initialData: {
|
|
387
|
+
name: "A",
|
|
388
|
+
},
|
|
389
|
+
keepValuesOnUnmount: false,
|
|
390
|
+
});
|
|
349
391
|
|
|
350
|
-
|
|
351
|
-
expect(nameField.initialValue.value).toBe(null)
|
|
352
|
-
expect(nameField.data.value).toBe(null)
|
|
392
|
+
const scope = effectScope();
|
|
353
393
|
|
|
354
|
-
|
|
394
|
+
scope.run(() => {
|
|
395
|
+
const nameField = form.defineField({ path: "name" });
|
|
355
396
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
397
|
+
expect(form.fields.value.length).toBe(1);
|
|
398
|
+
expect(nameField.data.value).toBe("A");
|
|
399
|
+
|
|
400
|
+
nameField.setData("Modified");
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
scope.stop();
|
|
404
|
+
|
|
405
|
+
expect(form.data.value.name).toBe("A");
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
describe("useForm - submit handler", () => {
|
|
409
|
+
it(
|
|
410
|
+
"it should not call the handler when validation errors exist",
|
|
411
|
+
{ timeout: 500 },
|
|
412
|
+
async () => {
|
|
413
|
+
const initialData = ref({
|
|
414
|
+
name: null as null | number,
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
const schema = z.object({
|
|
418
|
+
name: z.number().min(5),
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
const form = useForm({
|
|
422
|
+
initialData,
|
|
423
|
+
schema,
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
const nameField = form.getField("name");
|
|
427
|
+
|
|
428
|
+
const cb = vi.fn();
|
|
429
|
+
|
|
430
|
+
const handler = form.submitHandler(cb);
|
|
431
|
+
|
|
432
|
+
await handler(new SubmitEvent("submit"));
|
|
433
|
+
|
|
434
|
+
expect(form.isValidated.value).toBe(true);
|
|
435
|
+
expect(cb).not.toHaveBeenCalled();
|
|
436
|
+
expect(nameField.errors.value?.length).toBe(1);
|
|
437
|
+
},
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
it(
|
|
441
|
+
"it should call the handler when no validation errors exist",
|
|
442
|
+
{ timeout: 500 },
|
|
443
|
+
async () => {
|
|
444
|
+
const initialData = ref({
|
|
445
|
+
name: 10,
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
const schema = z.object({
|
|
449
|
+
name: z.number().min(5),
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
const form = useForm({
|
|
453
|
+
initialData,
|
|
454
|
+
schema,
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
const nameField = form.getField("name");
|
|
458
|
+
|
|
459
|
+
const cb = vi.fn();
|
|
460
|
+
|
|
461
|
+
const handler = form.submitHandler(cb);
|
|
462
|
+
|
|
463
|
+
await handler(new SubmitEvent("submit"));
|
|
464
|
+
|
|
465
|
+
expect(form.isValidated.value).toBe(true);
|
|
466
|
+
expect(cb).toHaveBeenCalled();
|
|
467
|
+
expect(nameField.errors.value?.length).toBe(0);
|
|
468
|
+
},
|
|
469
|
+
);
|
|
470
|
+
});
|
|
471
|
+
});
|