Upload
Upload component. It has been refactored to stay broadly compatible with the previous version while adding many default behaviors. See the API section for details.
Upload behavior can be divided into two broad categories.
The first only provides file selection. File binaries are uploaded to the backend together with the Formily Form values when the user submits the form.
The second uploads files before the form is submitted, which is the more common case in practice, such as uploading to OSS in advance. In this mode, form submission does not send file binaries directly. Instead, it submits strings such as URLs or other backend identifiers that reference the uploaded files.
The upload behavior itself is controlled by Element Plus Upload props such as action and httpRequest.
The file list shown to the user and the final value submitted by the form are intentionally separated and converted in one direction only. When ElUpload's file list changes, the component synchronizes the latest list to Field.dataSource, transforms it with formatValue, and emits update:modelValue to update Field.value. Changes to Field.value do not update Field.dataSource in the opposite direction.
The main exception is form rehydration. When restoring existing data, setting Field.value is not enough. You also need to construct the component's fileList (dataSource) yourself. How much detail you include in that fileList depends on your actual business needs.
Markup Schema Example
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import {
Form,
FormButtonGroup,
FormItem,
Submit,
Upload,
} from '@silver-formily/element-plus'
import { createSchemaField } from '@silver-formily/vue'
import { ElButton } from 'element-plus'
import { h } from 'vue'
function UploadButton() {
return h(ElButton, {}, { default: () => 'Upload Image' })
}
const form = createForm()
const { SchemaField, SchemaArrayField } = createSchemaField({
components: {
FormItem,
Upload,
},
})
async function onSubmit(value: Record<string, any>) {
console.log(value)
}
</script>
<template>
<Form :form="form" :label-col="4" :wrapper-col="10">
<SchemaField>
<SchemaArrayField
name="upload"
title="Upload"
x-decorator="FormItem"
x-component="Upload"
:x-component-props="{
action: 'https://run.mocky.io/v3/4ddf3c65-5202-4b56-87ad-ef7314e84fdc',
textContent: 'Upload',
}"
required
/>
<SchemaArrayField
name="upload2"
title="Card Upload"
x-decorator="FormItem"
x-component="Upload"
:x-component-props="{
listType: 'picture-card',
action: '#',
}"
required
/>
<SchemaArrayField
name="upload3"
title="Drag Upload"
x-decorator="FormItem"
x-component="Upload"
:x-component-props="{
action: 'https://formily-vue.free.beeceptor.com/file',
textContent: 'Drop files here, or click to upload',
drag: true,
}"
required
/>
<SchemaArrayField
name="custom"
title="Custom Button"
x-decorator="FormItem"
x-component="Upload"
:x-component-props="{
action: 'https://formily-vue.free.beeceptor.com/file',
}"
required
:x-content="UploadButton"
/>
</SchemaField>
<FormButtonGroup align-form-item>
<Submit @submit="onSubmit">
Submit
</Submit>
</FormButtonGroup>
</Form>
</template>JSON Schema Example
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import {
Form,
FormButtonGroup,
FormItem,
Submit,
Upload,
} from '@silver-formily/element-plus'
import { createSchemaField } from '@silver-formily/vue'
import { ElButton } from 'element-plus'
import { h } from 'vue'
function UploadButton() {
return h(ElButton, {}, { default: () => 'Upload Image' })
}
const schema = {
type: 'object',
properties: {
base: {
'type': 'array',
'title': 'Upload',
'x-decorator': 'FormItem',
'x-component': 'Upload',
'x-component-props': {
action: 'https://formily-vue.free.beeceptor.com/file',
textContent: 'Upload',
},
'required': true,
},
card: {
'type': 'array',
'title': 'Card Upload',
'x-decorator': 'FormItem',
'x-component': 'Upload',
'x-component-props': {
listType: 'picture-card',
action: 'https://formily-vue.free.beeceptor.com/file',
},
'required': true,
},
drag: {
'type': 'array',
'title': 'Drag Upload',
'x-decorator': 'FormItem',
'x-component': 'Upload',
'x-component-props': {
action: 'https://formily-vue.free.beeceptor.com/file',
textContent: 'Drop files here, or click to upload',
drag: true,
},
'required': true,
},
custom: {
'type': 'array',
'title': 'Custom Button',
'x-decorator': 'FormItem',
'x-component': 'Upload',
'x-component-props': {
action: 'https://formily-vue.free.beeceptor.com/file',
},
'x-content': UploadButton,
'required': true,
},
},
}
const form = createForm()
const { SchemaField } = createSchemaField({
components: {
FormItem,
Upload,
},
})
async function onSubmit(value: Record<string, any>) {
console.log(value)
}
</script>
<template>
<Form :form="form" :label-col="4" :wrapper-col="10">
<SchemaField :schema="schema" />
<FormButtonGroup align-form-item>
<Submit @submit="onSubmit">
Submit
</Submit>
</FormButtonGroup>
</Form>
</template>Template Example
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import {
Form,
FormButtonGroup,
FormItem,
Submit,
Upload,
} from '@silver-formily/element-plus'
import { ArrayField } from '@silver-formily/vue'
import { ElButton } from 'element-plus'
import { h } from 'vue'
function UploadButton() {
return h(ElButton, {}, { default: () => 'Upload Image' })
}
const form = createForm()
async function onSubmit(value: Record<string, any>) {
console.log(value)
}
</script>
<template>
<Form :form="form" :label-col="4" :wrapper-col="10">
<ArrayField
name="upload"
title="Upload"
:decorator="[FormItem]"
:component="[
Upload,
{
action: 'https://formily-vue.free.beeceptor.com/file',
textContent: 'Upload',
},
]"
required
/>
<ArrayField
name="upload2"
title="Card Upload"
:decorator="[FormItem]"
:component="[
Upload,
{
listType: 'picture-card',
action: 'https://formily-vue.free.beeceptor.com/file',
},
]"
required
/>
<ArrayField
name="upload3"
title="Drag Upload"
:decorator="[FormItem]"
:component="[
Upload,
{
action: 'https://formily-vue.free.beeceptor.com/file',
textContent: 'Drop files here, or click to upload',
drag: true,
},
]"
required
/>
<ArrayField
name="custom"
title="Custom Button"
:decorator="[FormItem]"
:component="[
Upload,
{
action: 'https://formily-vue.free.beeceptor.com/file',
},
]"
required
>
<UploadButton />
</ArrayField>
<FormButtonGroup align-form-item>
<Submit @submit="onSubmit">
Submit
</Submit>
</FormButtonGroup>
</Form>
</template>API
Props
Tip
- The component maps
fileListtoField.dataSourceinstead ofField.value. WhendataSourcechanges, it produces the form value withformatValueand updatesField.valuethroughupdate:modelValue. - When
limitis1, the previous file is automatically replaced. This behavior is built in and cannot be overridden. - If
acceptcontains the stringimageand an item infileListprovides aurl, image preview is enabled automatically. If you want to disable that behavior, setonPreviewto an empty function.
| Prop | Description | Type | Default |
|---|---|---|---|
textContent | Text displayed on the upload button. Placement varies by upload mode. | string | '' |
errorAdaptor | Error adapter used to customize how error messages are shown | Function | error => error?.message |
formatValue 1.0.0 | Formatter that converts the file list into the final value submitted by the form | Function | fileList => fileList |
fileList 1.0.0 | File list, mapped to dataSource and forwarded to ElUpload.fileList | array | [] |
imageViewerProps 1.0.0 | Props for the image viewer, used to customize image preview behavior when uploading images | object | { teleported: true, showProgress: true } |
onChange and onUpdate:fileList are consumed internally and are not forwarded. Do not use them directly. For all other props and events, see https://element-plus.org/en-US/component/upload.html
Slots 1.0.0
The component inherits every slot from ElUpload.
Tip
You can use textContent, list-type, and drag to generate interactions that would otherwise require slots. See the demos for concrete examples.
Get Instance Example 1.0.0
Used to access the ElUpload instance. For exposed methods, see the Element Plus documentation.
const uploadRef: Ref<UploadInstance> = fieldRef.value.invoke('getElUploadRef')