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.
This component handles those two flows differently. When action is '#' and httpRequest is not configured, it is treated as the first mode. In that case, onChange is triggered when the status of items in fileList changes.
When either action or httpRequest is configured, it is treated as the second mode. In that case, onChange is triggered after the request completes, which means when the response field of any item in fileList changes.
The file list shown to the user and the final value submitted by the form are intentionally separated and flow in one direction only. When fileList (dataSource) changes, onChange is triggered to update Field.value. But when value changes, dataSource is not updated automatically. That design matches most business cases: users add or remove files from fileList, and the final submitted value is derived from it.
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 now maps
fileListtoField.dataSourceinstead ofField.value. WhendataSourcechanges, it triggersonChange, andvalueis produced throughformatValue. - 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 reserved and should not be used 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')