File inputs
Single file →
File | null. Multiple →readonly File[]. Live handles, ready forFormDataor your upload pipeline.
- Category
- Directive binding
- Element
<input type="file"> · <input type="file" multiple>- Modifiers
- none
- Leaf types
File | null (single) · readonly File[] (multiple)
Pick a file in the single input to watch the avatar slot fill in with the file name + size. Pick more in the multi-input below to see them stack; the directive writes a File[] in the order the picker returned them. Both surfaces hand you live File handles you can append to FormData or stream into an upload.
Single file → File | null
<input v-register="form.register('avatar')" type="file" accept="image/*" />
const form = useForm({
schema: z.object({
avatar: z.file().nullable(),
}),
defaultValues: { avatar: null },
})
form.values.avatar // File | null
Selecting a file writes the File handle into storage. Clearing the input (or selecting then cancelling) writes null.
Multiple files → File
<input v-register="form.register('attachments')" type="file" multiple />
const form = useForm({
schema: z.object({
attachments: z.array(z.file()),
}),
defaultValues: { attachments: [] },
})
form.values.attachments // readonly File[]
Every file in the picker selection lands in the array, in picker order. Re-selecting replaces the array; the input never accumulates across picks.
Uploading via FormData
Live File handles work directly with the upload pipelines you'd reach for anyway:
const onSubmit = form.handleSubmit(async (values) => {
const body = new FormData()
body.append('avatar', values.avatar!)
for (const file of values.attachments) {
body.append('attachments', file)
}
await fetch('/api/upload', { method: 'POST', body })
})
The schema's z.file() leaf type carries the constraint through validation; refinements like .min(size), .max(size), .mime([...]) surface in form.errors.<path> like any other validator.
Reset behavior
form.reset() clears the file input back to null / []. The directive also resets the underlying <input>'s value attribute, so the picker shows "No file chosen" after the reset, no stale filename hanging around.
Where to next
reset&resetField: programmatic clearing.- Schema-driven coercion: how File leaves move through the directive.
handleSubmit: wraps your upload callback in the validation gate.