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.

Playground.vuevue
<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

NameTypeTSDefaultDescription
modelValuearrayArray<unknown>[]Selected local files or existing uploaded file metadata.
acceptstringstring''Native accept string, such as image/*,.pdf.
multiplebooleanbooleantrueAllow multiple files.
maxFilesnumbernumber0Maximum file count. Use 0 for no explicit limit.
maxSizenumbernumber0Maximum file size in bytes. Use 0 for no explicit limit.
browseLabelstringstring'Choose files'Browse button label.
emptyTitlestringstring'Drop files here'Title shown when no files are selected.
emptyDescriptionstringstring'or browse from your device'Helper copy shown in the dropzone.

Field props

NameTypeTSDefaultDescription
idstringstring''Optional ID override. By default parent forms derive the input ID from the field path using underscores.
namestringstring''Local field name. Parent forms derive the full field path and native HTML name from the form hierarchy.
labelstringstring''Visible field label.
descriptionstringstring''Optional helper copy below the field.
placeholderstringstring''Placeholder shown when the control is empty.
requiredbooleanbooleanfalseMark the field as required.
disabledbooleanbooleanfalseDisable field interaction.
readOnlybooleanbooleanfalseShow the value but prevent editing.
invalidbooleanbooleanfalseMark the field invalid.
errors
[
	{
		name: "Validation name",
		message: "Error message",
	}
]
array | object | stringArray<ErrorsItem
type ErrorsItem = {
	name?: string; // Name
	message?: string; // Message
};
>
[]Validation errors for this field.
visiblebooleanbooleantrueShow or hide the field.
validatorsarrayArray<unknown>[]Validators attached to this field. Use functions in Vue code, or serializable records such as { name: "minLength", props: { min: 2 } } in generated schemas.
validateOnBlurbooleanbooleantrueRun validators when the field loses focus.
chrome'field' | falsestring'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

NamePayloadDescription
@update:modelValueArray<File | DomUploadedFile>Fired when the local file list changes.
@addArray<File>Fired with accepted local File objects.
@remove{ file, index }Fired when a file row is removed.
@rejectArray<DomFileUploadRejection>Fired when files fail accept, size, or count checks.
@focusFocusEventFired when the native file input receives focus.
@blurFocusEventFired when the native file input loses focus.

Names auto-detected from defineEmits and source emit() calls; payload and description from __doc.events when present.