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