@tanstack/vue-form 0.16.0 → 0.16.2
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/README.md +1 -1
- package/dist/cjs/useField.cjs.map +1 -1
- package/dist/cjs/useField.d.cts +4 -4
- package/dist/esm/useField.d.ts +4 -4
- package/dist/esm/useField.js.map +1 -1
- package/package.json +5 -3
- package/src/tests/useField.test.tsx +119 -0
- package/src/useField.tsx +13 -4
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@tanstack/vue-form",
|
3
|
-
"version": "0.16.
|
3
|
+
"version": "0.16.2",
|
4
4
|
"description": "Powerful, type-safe forms for Vue.",
|
5
5
|
"author": "tannerlinsley",
|
6
6
|
"license": "MIT",
|
@@ -34,7 +34,7 @@
|
|
34
34
|
],
|
35
35
|
"dependencies": {
|
36
36
|
"@tanstack/vue-store": "^0.3.1",
|
37
|
-
"@tanstack/form-core": "0.16.
|
37
|
+
"@tanstack/form-core": "0.16.2"
|
38
38
|
},
|
39
39
|
"devDependencies": {
|
40
40
|
"@vitejs/plugin-vue": "^5.0.4",
|
@@ -49,7 +49,9 @@
|
|
49
49
|
"test:types:versions49": "node ../../node_modules/typescript49/lib/tsc.js --project tsconfig.legacy.json",
|
50
50
|
"test:types:versions50": "node ../../node_modules/typescript50/lib/tsc.js",
|
51
51
|
"test:types:versions51": "node ../../node_modules/typescript51/lib/tsc.js",
|
52
|
-
"test:types:versions52": "tsc",
|
52
|
+
"test:types:versions52": "node ../../node_modules/typescript52/lib/tsc.js",
|
53
|
+
"test:types:versions53": "node ../../node_modules/typescript53/lib/tsc.js",
|
54
|
+
"test:types:versions54": "tsc",
|
53
55
|
"test:types": "pnpm run \"/^test:types:versions.*/\"",
|
54
56
|
"fixme:test:lib": "pnpm run test:2 && pnpm run test:2.7 && pnpm run test:3",
|
55
57
|
"test:lib": "vitest",
|
@@ -251,6 +251,106 @@ describe('useField', () => {
|
|
251
251
|
expect(getByText(error)).toBeInTheDocument()
|
252
252
|
})
|
253
253
|
|
254
|
+
it('should handle arrays with subvalues', async () => {
|
255
|
+
const fn = vi.fn()
|
256
|
+
|
257
|
+
type CompVal = { people: Array<string> }
|
258
|
+
|
259
|
+
const Comp = defineComponent(() => {
|
260
|
+
const form = useForm({
|
261
|
+
defaultValues: {
|
262
|
+
people: [],
|
263
|
+
} as CompVal,
|
264
|
+
onSubmit: ({ value }) => fn(value),
|
265
|
+
})
|
266
|
+
|
267
|
+
return () => (
|
268
|
+
<div>
|
269
|
+
<form
|
270
|
+
onSubmit={(e) => {
|
271
|
+
e.preventDefault()
|
272
|
+
e.stopPropagation()
|
273
|
+
void form.handleSubmit()
|
274
|
+
}}
|
275
|
+
>
|
276
|
+
<form.Field name="people">
|
277
|
+
{({
|
278
|
+
field,
|
279
|
+
}: {
|
280
|
+
field: FieldApi<CompVal, 'people', never, never>
|
281
|
+
}) => (
|
282
|
+
<div>
|
283
|
+
{field.state.value.map((_, i) => {
|
284
|
+
return (
|
285
|
+
<form.Field key={i} name={`people[${i}]`}>
|
286
|
+
{({
|
287
|
+
field: subField,
|
288
|
+
}: {
|
289
|
+
field: FieldApi<
|
290
|
+
CompVal,
|
291
|
+
`people[${number}]`,
|
292
|
+
never,
|
293
|
+
never
|
294
|
+
>
|
295
|
+
}) => (
|
296
|
+
<div>
|
297
|
+
<label>
|
298
|
+
<div>Name for person {i}</div>
|
299
|
+
<input
|
300
|
+
value={subField.state.value}
|
301
|
+
onChange={(e) =>
|
302
|
+
subField.handleChange(
|
303
|
+
(e.target as HTMLInputElement).value,
|
304
|
+
)
|
305
|
+
}
|
306
|
+
/>
|
307
|
+
</label>
|
308
|
+
<button
|
309
|
+
onClick={() => field.removeValue(i)}
|
310
|
+
type="button"
|
311
|
+
>
|
312
|
+
Remove person {i}
|
313
|
+
</button>
|
314
|
+
</div>
|
315
|
+
)}
|
316
|
+
</form.Field>
|
317
|
+
)
|
318
|
+
})}
|
319
|
+
<button onClick={() => field.pushValue('')} type="button">
|
320
|
+
Add person
|
321
|
+
</button>
|
322
|
+
</div>
|
323
|
+
)}
|
324
|
+
</form.Field>
|
325
|
+
<button type="submit">Submit</button>
|
326
|
+
</form>
|
327
|
+
</div>
|
328
|
+
)
|
329
|
+
})
|
330
|
+
|
331
|
+
const { queryByText, getByText, findByLabelText, findByText } = render(Comp)
|
332
|
+
expect(queryByText('Name for person 0')).not.toBeInTheDocument()
|
333
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
334
|
+
await user.click(getByText('Add person'))
|
335
|
+
const input = await findByLabelText('Name for person 0')
|
336
|
+
expect(input).toBeInTheDocument()
|
337
|
+
await user.type(input, 'John')
|
338
|
+
|
339
|
+
await user.click(getByText('Add person'))
|
340
|
+
const input2 = await findByLabelText('Name for person 1')
|
341
|
+
expect(input).toBeInTheDocument()
|
342
|
+
await user.type(input2, 'Jack')
|
343
|
+
|
344
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
345
|
+
expect(queryByText('Name for person 1')).toBeInTheDocument()
|
346
|
+
await user.click(getByText('Remove person 1'))
|
347
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
348
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
349
|
+
|
350
|
+
await user.click(await findByText('Submit'))
|
351
|
+
expect(fn).toHaveBeenCalledWith({ people: ['John'] })
|
352
|
+
})
|
353
|
+
|
254
354
|
it('should handle arrays with subvalues', async () => {
|
255
355
|
const fn = vi.fn()
|
256
356
|
|
@@ -305,6 +405,12 @@ describe('useField', () => {
|
|
305
405
|
}
|
306
406
|
/>
|
307
407
|
</label>
|
408
|
+
<button
|
409
|
+
onClick={() => field.removeValue(i)}
|
410
|
+
type="button"
|
411
|
+
>
|
412
|
+
Remove person {i}
|
413
|
+
</button>
|
308
414
|
</div>
|
309
415
|
)}
|
310
416
|
</form.Field>
|
@@ -327,10 +433,23 @@ describe('useField', () => {
|
|
327
433
|
|
328
434
|
const { queryByText, getByText, findByLabelText, findByText } = render(Comp)
|
329
435
|
expect(queryByText('Name for person 0')).not.toBeInTheDocument()
|
436
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
330
437
|
await user.click(getByText('Add person'))
|
331
438
|
const input = await findByLabelText('Name for person 0')
|
332
439
|
expect(input).toBeInTheDocument()
|
333
440
|
await user.type(input, 'John')
|
441
|
+
|
442
|
+
await user.click(getByText('Add person'))
|
443
|
+
const input2 = await findByLabelText('Name for person 1')
|
444
|
+
expect(input).toBeInTheDocument()
|
445
|
+
await user.type(input2, 'Jack')
|
446
|
+
|
447
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
448
|
+
expect(queryByText('Name for person 1')).toBeInTheDocument()
|
449
|
+
await user.click(getByText('Remove person 1'))
|
450
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
451
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
452
|
+
|
334
453
|
await user.click(await findByText('Submit'))
|
335
454
|
expect(fn).toHaveBeenCalledWith({ people: [{ name: 'John', age: 0 }] })
|
336
455
|
})
|
package/src/useField.tsx
CHANGED
@@ -40,7 +40,7 @@ export type UseField<
|
|
40
40
|
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
41
41
|
>(
|
42
42
|
opts: Omit<
|
43
|
-
UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,
|
43
|
+
UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,
|
44
44
|
'form'
|
45
45
|
>,
|
46
46
|
) => {
|
@@ -133,7 +133,8 @@ type FieldComponentProps<
|
|
133
133
|
TFormValidator extends
|
134
134
|
| Validator<TParentData, unknown>
|
135
135
|
| undefined = undefined,
|
136
|
-
|
136
|
+
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
137
|
+
> = UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>
|
137
138
|
|
138
139
|
export type FieldComponent<
|
139
140
|
TParentData,
|
@@ -148,7 +149,13 @@ export type FieldComponent<
|
|
148
149
|
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
149
150
|
>(
|
150
151
|
fieldOptions: Omit<
|
151
|
-
FieldComponentProps<
|
152
|
+
FieldComponentProps<
|
153
|
+
TParentData,
|
154
|
+
TName,
|
155
|
+
TFieldValidator,
|
156
|
+
TFormValidator,
|
157
|
+
TData
|
158
|
+
>,
|
152
159
|
'form'
|
153
160
|
>,
|
154
161
|
context: SetupContext<
|
@@ -184,12 +191,14 @@ export const Field = defineComponent(
|
|
184
191
|
TFormValidator extends
|
185
192
|
| Validator<TParentData, unknown>
|
186
193
|
| undefined = undefined,
|
194
|
+
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
187
195
|
>(
|
188
196
|
fieldOptions: UseFieldOptions<
|
189
197
|
TParentData,
|
190
198
|
TName,
|
191
199
|
TFieldValidator,
|
192
|
-
TFormValidator
|
200
|
+
TFormValidator,
|
201
|
+
TData
|
193
202
|
>,
|
194
203
|
context: SetupContext,
|
195
204
|
) => {
|