MazDropzone
MazDropzone is a powerful and flexible file upload component with drag & drop support, progress tracking, and customizable UI. Perfect for handling single or multiple file uploads in your Vue applications.
Before use it, you should install the MazUi plugin in your project, follow instructions in Getting Started
TIP
This component can be translated globally using the MazUi plugin.
Key Features
- 🎯 Drag & drop support
- 📁 Single or multiple file uploads
- 🖼️ Image preview thumbnails
- 🚀 Auto upload support
- ⚡ Async file processing
- 🎨 Fully customizable UI
- 🌐 Support for various file types
- ⚙️ Extensive configuration options
- 🔒 File validation (size, type, count)
- 🌍 Internationalization support
Error codes
| Error Code | Description | Trigger |
|---|---|---|
FILE_SIZE_EXCEEDED | File size exceeds the allowed limit | When a file is larger than maxFileSize (in MB) |
FILE_SIZE_TOO_SMALL | File size is below the minimum limit | When a file is smaller than minFileSize (in MB) |
MAX_FILES_EXCEEDED | Maximum number of allowed files exceeded | When trying to add more files than maxFiles or more than 1 file if multiple=false |
FILE_TYPE_NOT_ALLOWED | File type is not allowed | When the file's MIME type doesn't match the specified dataTypes |
FILE_DUPLICATED | An identical file already exists | When allowDuplicates=false and a file with the same name, size and type already exists |
NO_FILES_TO_UPLOAD | No files to upload | When starting upload but there are no files in the dropzone |
FILE_UPLOAD_ERROR | Error during individual file upload | When uploading a specific file fails (single mode) |
FILE_UPLOAD_ERROR_MULTIPLE | Error during batch upload | When uploading multiple files fails (multiple mode) |
NO_URL | No upload URL configured | When attempting auto-upload without defining the url prop |
Error handling example
View code
<script setup>
function handleError({ code, files }) {
switch (code) {
case 'FILE_SIZE_EXCEEDED':
console.log('File too large:', files[0].name)
break
case 'FILE_TYPE_NOT_ALLOWED':
console.log('File type not allowed:', files[0].type)
break
case 'MAX_FILES_EXCEEDED':
console.log('Too many files selected')
break
// ...
}
}
</script>
<template>
<MazDropzone
:max-file-size="5"
:max-files="3"
:data-types="['image/*', 'application/pdf']"
:allow-duplicates="false"
@error="handleError"
/>
</template>Basic Usage
<script setup lang="ts">
import { useToast } from 'maz-ui/composables'
import { ref } from 'vue'
const toast = useToast()
const files = ref<File[]>([])
const dropzone = ref<InstanceType<typeof MazDropzone>>()
function onUploadSuccess({ file, response }) {
console.log('Upload success:', file, response)
toast.success(`File ${file.name} uploaded successfully`)
}
function onUploadError({ file, code, error }) {
console.error('Upload failed:', file, code, error)
toast.error(`File ${file.name} upload failed: ${code} - ${error}`)
}
function onError({ files, event, code }) {
console.error('Error:', files, event, code)
toast.error(`${files?.length} files upload failed: ${code} - ${files?.map(file => file.name).join(', ')}`)
}
</script>
<template>
<MazDropzone
v-model="files"
:data-types="['image/*', '.zip', '.strings', '.json', '.stringsdict']"
:max-file-size="3"
:max-files="5"
:max-concurrent-uploads="5"
url="https://httpbin.org/post"
:request-options="{
headers: { 'My-Awesome-Header': 'header value' },
}"
@upload-success="onUploadSuccess"
@upload-error="onUploadError"
@error="onError"
/>
<MazBtn :loading="dropzone?.isUploading" @click="dropzone?.uploadFiles()">
Upload Files
</MazBtn>
</template>File Type Restrictions
You can restrict allowed file types using the data-types prop:
<script lang="ts" setup>
const acceptedFormats = [
'.strings',
'.stringsdict',
'.plist',
'.xliff',
'.xlf',
'.xml',
'.json',
'.yaml',
'.yml',
'.po',
'.pot',
'.mo',
'.properties',
'.arb',
'.csv',
'.tsv',
'.txt',
'text/*',
'application/json',
'text/xml',
'application/xml',
'text/yaml',
'text/html',
'image/svg+xml',
'video/mp4',
'video/quicktime',
'video/mpeg',
'video/ogg',
'video/webm',
'audio/*',
]
</script>
<template>
<MazDropzone
v-model="files"
:data-types="acceptedFormats"
:max-file-size="5"
:max-files="5"
@error="onError"
/>
</template>Auto Upload
Enable automatic file upload using the auto-upload prop. Files can be uploaded individually (single) in separate requests or all at once (multiple) in a single request:
<MazDropzone
v-model="files"
auto-upload="single"
url="https://your-upload-endpoint.com/upload"
@upload-success="onUploadSuccess"
@upload-error="onUploadError"
@error="onError"
/>You can also upload all files at once using multiple:
TIP
Multiple upload is allowed:
- when
max-filesis greater than 1 - when
auto-uploadis set tomultiple - when
multipleprop is set totrue
<template>
<MazDropzone
v-model="files"
auto-upload="multiple"
url="https://your-upload-endpoint.com/upload"
@upload-success-multiple="onUploadSuccessMultiple"
@upload-error-multiple="onUploadErrorMultiple"
@error="onError"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useToast } from 'maz-ui/composables'
const files = ref<File[]>([])
const toast = useToast()
const onUploadSuccessMultiple = ({ files, response }) => {
console.log('Upload multiple success:', files, response)
toast.success(`${files.length} files uploaded successfully`)
}
const onUploadErrorMultiple = ({ files, code, error }) => {
console.error('Upload mulitple failed:', files, code, error)
toast.error(`${files.length} files upload failed: ${code} - ${error}`)
}
</script>Custom Upload Area
Customize the upload area using slots:
<MazDropzone v-model="files" @error="onError">
<template #no-files-area="{ handleFileInputClick }">
<div class="flex flex-col items-center gap-4">
<MazIcon icon="/arrow-up-on-square.svg" class="text-4xl" />
<p>Drop your files here or click to browse</p>
<MazBtn @click="handleFileInputClick"> Select Files </MazBtn>
</div>
</template>
</MazDropzone>Custom Translations
Using translations prop
Customize text messages using the translations prop:
<MazDropzone
v-model="files"
:translations="{
dragAndDrop: 'Drag files here',
selectFile: 'browse files',
fileInfos: 'Accepted files: Images up to 5MB'
}"
@error="onError"
/>Using MazUi plugin
You can also use the MazUi plugin to customize the translations:
View code
import { MazUi } from 'maz-ui/plugins/maz-ui'
app.use(MazUi, {
translations: {
locale: 'en',
messages: {
en: {
dropzone: {
dragAndDrop: 'Drag files here',
selectFile: 'select files',
divider: 'or',
fileMaxCount: 'Maximum {count} files',
fileMaxSize: 'Maximum {size} MB',
fileTypes: 'Allowed file types: {types}',
},
},
},
},
})Custom Upload Request
Customize the upload request using uploadUrl, requestOptions and transformBody:
<MazDropzone
v-model="files"
url="/api/upload"
:request-options="{
method: 'POST',
headers: {
'Authorization': 'Bearer token123'
},
}"
:transform-body="(formData, files) => {
// Add additional data to FormData
formData.append('userId', '123')
formData.append('fileCount', files.length.toString())
return formData
}"
@error="onError"
/>Props
| Name | Description | Type | Required | Default | Possible values |
|---|---|---|---|---|---|
| id | The id of the dropzone | string | No | - | - |
| multiple | Allow multiple files to be uploaded. | boolean | No | false | - |
| data-types | Allowed data types/MIME types for files (e.g. ['application/json']) | string[] | No | ['*\/*'] | - |
| prevent-default-for-unhandled | Prevent default behavior for unhandled drag & drop events. | boolean | No | true | - |
| max-file-size | Maximum file size in MB. | number | No | - | - |
| max-files | Maximum number of files allowed. | number | No | - | - |
| disabled | Disable the dropzone | boolean | No | false | - |
| preview | Show file preview | boolean | No | true | - |
| min-file-size | Minimum file size in MB | number | No | - | - |
| allow-duplicates | Allow duplicates | boolean | No | false | - |
| translations | Translations - Custom translations for the component | { dragAndDrop?: string | undefined; selectFile?: string | undefined; divider?: string | undefined; fileMaxCount?: string | undefined; fileMaxSize?: string | undefined; fileTypes?: string | undefined; types?: { image?: string | undefined;... | No | - | - |
| color | Main color of the component | "primary" | "secondary" | "accent" | "info" | "success" | "warning" | "destructive" | "contrast" | "transparent" | No | "primary" | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'destructive' | 'contrast' | 'transparent' |
| remove-file-btn-props | MazBtn props MazBtn props | MazBtnProps | No | {} | - |
| spinner-props | MazSpinner props MazSpinner props | MazSpinnerProps | No | {} | - |
| auto-upload | Auto upload files - If set to multiple, all files will be uploaded at once in a single request. If set to single, files will be uploaded one by one in separate requests. If set to false, no upload will be done automatically. | false | "multiple" | "single" | No | false | 'multiple' | 'single' |
| url | Upload URL - If set, files will be uploaded to the given URL. | string | No | - | - |
| request-options | Request options - Request options to be used for the upload (using fetch) Request options | RequestInit | No | - | - |
| transform-body | Transform the body of the request | ((formData: FormData) => BodyInit | null | undefined) | No | - | - |
| max-concurrent-uploads | Maximum number of concurrent uploads - Limit the number of files uploaded simultaneously to avoid overwhelming the server | number | No | 5 | - |
| model-value | v-model The files data | MazDropzoneFileData[] | No | [] | - |
Events
| Event name | Payload | Description |
|---|---|---|
| add | value: File | Event emitted when a file is added to the dropzone |
| error | values: { files: File[] | null; event: DragEvent | null; code: MazDropzoneErrorCode; } | Event emitted when an error occurs |
| drop | values: { files: File[] | null; event: DragEvent; } | Event emitted when files are dropped in the dropzone |
| update:modelValue | value: MazDropzoneFileData[] | |
| enter | values: { files: File[] | null; event: DragEvent; } | Event emitted when dragged files enter the dropzone |
| leave | values: { files: File[] | null; event: DragEvent; } | Event emitted when dragged files leave the dropzone |
| over | values: { files: File[] | null; event: DragEvent; } | Event emitted when dragged files are over the dropzone |
| remove | value: File | Event emitted when a file is removed from the dropzone |
| upload-error | values: { file: File; code: MazDropzoneErrorCode; error: unknown; } | Event emitted when an error occurs during file upload |
| upload-error-multiple | values: { files: File[]; code: MazDropzoneErrorCode; error: unknown; } | Event emitted when an error occurs during multiple files upload |
| upload-success | values: { file: File; response?: Response | undefined; } | Event emitted when a file is successfully uploaded |
| upload-success-multiple | values: { files: File[]; response?: Response | undefined; } | Event emitted when multiple files are successfully uploaded |
Slots
| Name | Description | Bindings |
|---|---|---|
| files-area | Slot to customize the files area | filesData MazDropzoneFileData[] - The files data |
| file-item | Slot to customize the file item | file MazDropzoneFileData - The drop file data |
| no-files-area | Slot to customize the no files area | selectFile () => void - The function to select the file |
| upload-icon | Slot to customize the upload icon | - |
Expose
uploadFiles
Upload files
uploadFilesMultiple
Upload multiple files
getFormData
Get form data
getFormDataMultiple
Get form data multiple
reset
Reset the files
isUploading
Check if the files are uploading
addFile
Add a file to the dropzone
removeFile
Remove a file from the dropzone