Component
File upload
<DomFileUpload>A generic local file picker and dropzone for forms. Uploading, persistence, and media APIs stay parent-owned.
Playground
Try every prop live
File upload playground
The component owns selection UI and validation only. Your app owns upload, progress, and persistence.
Drop files here
or browse from your device
Select local files; upload them from the parent.
<script setup>
import { reactive } from 'vue';
import { DomFileUpload } from '@getdom/studio/vue';
const data = reactive({
"modelValue": [],
"id": "",
"name": "",
"label": "Files",
"description": "Select local files; upload them from the parent.",
"placeholder": "",
"required": false,
"disabled": false,
"readOnly": false,
"invalid": false,
"errors": [],
"visible": true,
"validators": [],
"validateOnBlur": true,
"chrome": "field",
"accept": "image/*,.pdf",
"multiple": true,
"maxFiles": 3,
"maxSize": 0,
"browseLabel": "Choose files",
"emptyTitle": "Drop files here",
"emptyDescription": "or browse from your device"
});
</script>
<template>
<DomFileUpload
v-bind="data"
@update:modelValue="data.modelValue = $event"
/>
</template>Demo
Expense receipt
Mix existing uploaded file metadata with new local File objects, then let the parent handle upload work.
Choose files
or browse from your device
receipt-lunch.pdf
277.3 KB / application/pdf
Attach PDFs or images. The component only manages local selection.
<script setup>
import { ref } from 'vue';
import { DomAlert, DomFileUpload } from '../../../lib/vue';
const files = ref([
{
id: 'receipt-1844',
name: 'receipt-lunch.pdf',
size: 284000,
type: 'application/pdf',
url: '/files/receipt-1844',
},
]);
const rejected = ref([]);
</script>
<template>
<div class="w-full max-w-xl rounded-lg border border-border bg-canvas p-5 shadow-sm">
<DomFileUpload
v-model="files"
label="Receipt evidence"
description="Attach PDFs or images. The component only manages local selection."
accept="image/*,.pdf"
:max-files="3"
:max-size="5 * 1024 * 1024"
@reject="rejected = $event"
/>
<DomAlert
v-if="rejected.length"
class="mt-4"
tone="warning"
title="Some files were not added"
:description="rejected.map((item) => item.message).join(' ')"
/>
</div>
</template>
Reference
Props
Control props
| Name | Type | TS | Default | Description |
|---|---|---|---|---|
modelValue | array | Array<unknown> | [] | Selected local files or existing uploaded file metadata. |
accept | string | string | '' | Native accept string, such as image/*,.pdf. |
multiple | boolean | boolean | true | Allow multiple files. |
maxFiles | number | number | 0 | Maximum file count. Use 0 for no explicit limit. |
maxSize | number | number | 0 | Maximum file size in bytes. Use 0 for no explicit limit. |
browseLabel | string | string | 'Choose files' | Browse button label. |
emptyTitle | string | string | 'Drop files here' | Title shown when no files are selected. |
emptyDescription | string | string | 'or browse from your device' | Helper copy shown in the dropzone. |
Field props
| Name | Type | TS | Default | Description |
|---|---|---|---|---|
id | string | string | '' | Optional ID override. By default parent forms derive the input ID from the field path using underscores. |
name | string | string | '' | Local field name. Parent forms derive the full field path and native HTML name from the form hierarchy. |
label | string | string | '' | Visible field label. |
description | string | string | '' | Optional helper copy below the field. |
placeholder | string | string | '' | Placeholder shown when the control is empty. |
required | boolean | boolean | false | Mark the field as required. |
disabled | boolean | boolean | false | Disable field interaction. |
readOnly | boolean | boolean | false | Show the value but prevent editing. |
invalid | boolean | boolean | false | Mark the field invalid. |
errors | array | object | string | Array< | [] | Validation errors for this field. |
visible | boolean | boolean | true | Show or hide the field. |
validators | array | Array<unknown> | [] | Validators attached to this field. Use functions in Vue code, or serializable records such as { name: "minLength", props: { min: 2 } } in generated schemas. |
validateOnBlur | boolean | boolean | true | Run validators when the field loses focus. |
chrome | 'field' | false | string | 'field' | Render default field chrome, or false to render only the control while keeping form state wiring. |
Auto-generated from File upload.props and inline _edit hints.
Events
| Name | Payload | Description |
|---|---|---|
| @update:modelValue | Array<File | DomUploadedFile> | Fired when the local file list changes. |
| @add | Array<File> | Fired with accepted local File objects. |
| @remove | { file, index } | Fired when a file row is removed. |
| @reject | Array<DomFileUploadRejection> | Fired when files fail accept, size, or count checks. |
| @focus | FocusEvent | Fired when the native file input receives focus. |
| @blur | FocusEvent | Fired when the native file input loses focus. |
Names auto-detected from defineEmits and source emit() calls; payload and description from __doc.events when present.