File input
Contents
The File Input component provides different types of file uploads based on user needs. It ensures a smooth and structured way to upload images, logos, and user profile pictures.
If you are using it with vue, you should import the following:
import { create, supported, registerPlugin, getOptions, OptionTypes } from 'filepond'
import FilePondPluginFileValidateSize from 'filepond-plugin-file-validate-size'
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type'
import FilePondPluginImagePreview from 'filepond-plugin-image-preview'
import 'filepond/dist/filepond.min.css'
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css'
You can install them by
npm install vue-filepond filepond
npm i filepond-plugin-file-validate-size --save
npm i filepond-plugin-file-validate-type --save
npm i filepond-plugin-image-preview --save
General File Upload
The General File Upload component is designed for uploading various file types, including images, PDFs, and documents. It leverages the FilePond library for a smooth and intuitive upload experience.

HTML
<label class="form-label">صورة الغلاف</label>
<input class="js-filepond" type="file">
<!-- Usage Example -->
<GeneralFileInput
v-model="coverImage"
label="صورة الغلاف"
name="cover"
:allow-multiple="false"
accepted-file-types="image/*"
required
/>
<!-- Vue Component Code Block -->
<script>
import { ref, onMounted, onUnmounted, defineProps, defineEmits } from 'vue'
import { create, supported, registerPlugin, getOptions, OptionTypes } from 'filepond'
import FilePondPluginFileValidateSize from 'filepond-plugin-file-validate-size'
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type'
import FilePondPluginImagePreview from 'filepond-plugin-image-preview'
import 'filepond/dist/filepond.min.css'
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css'
registerPlugin(
FilePondPluginFileValidateSize,
FilePondPluginFileValidateType,
FilePondPluginImagePreview,
)
const types = {
boolean: Boolean,
int: Number,
number: Number,
string: String,
array: Array,
object: Object,
function: Function,
serverapi: Object,
}
const optionTypes = OptionTypes
const filepondProps = {}
const eventNames = []
const defaultOptions = getOptions()
for (const key in optionTypes) {
if (/^on/.test(key)) {
eventNames.push(key.replace(/^on/, ''))
continue
}
filepondProps[key] = {
type: types[optionTypes[key]] || String,
default: defaultOptions[key],
}
}
</script>
<script setup>
const props = defineProps({
label: String,
placeholder: String,
type: {
type: String,
default: 'text',
},
modelValue: Array,
required: Boolean,
className: String,
name: String,
id: String,
...filepondProps,
})
const emit = defineEmits(['update:modelValue', 'input', ...eventNames])
const pond = ref(null)
const inputElement = ref(null)
onMounted(() => {
if (inputElement.value && supported) {
const options = {
...props,
labelIdle: ' اسحب أو <span class="filepond--label-action"> أختر ملفًا </span> لتحميل الصورة',
// (All other Arabic labels...)
credits: false,
}
pond.value = create(inputElement.value, options)
for (const eventName of eventNames) {
pond.value.on(eventName, (...args) => {
const files = pond.value ? pond.value.getFiles() : []
emit('input', files)
emit('update:modelValue', files)
emit(eventName, ...args)
})
}
if (props.modelValue?.length) {
pond.value.files = props.modelValue
}
}
})
onUnmounted(() => {
if (pond.value) {
for (const eventName of eventNames) {
pond.value.off(eventName, (...args) => {
emit(eventName, ...args)
})
}
pond.value.destroy()
}
})
</script>
<template>
<div class="filepond--wrapper mb-3">
<label v-if="label" class="form-label">{{ label }}</label>
<input
ref="inputElement"
type="file"
:id="id"
:name="name"
:class="className"
:required="required"
:placeholder="placeholder"
:accept="acceptedFileTypes"
:multiple="allowMultiple"
:capture="captureMethod"
/>
</div>
</template>
HTML
<input type="file"
class="filepond"
name="filepond"
multiple
data-allow-reorder="true"
data-max-file-size="3MB"
data-max-files="3">
✅ Multiple File Uploads: Supports uploading multiple files simultaneously with multiple attribute.
✅ File Reordering: Drag & drop file reordering using data-allow-reorder="true".
✅ Ensure responsive layout adjustments for different screen sizes.
✅ Max Files: Define the maximum number of files that can be uploaded with data-max-files="3".
✅ Image Previews: Enable real-time previews of uploaded images.
✅ EXIF Orientation: Automatically correct image orientation based on EXIF metadata.
✅ Validation Plugins: Use additional plugins to validate file types, sizes, and other parameters.
Logo/Brand Image Upload
Used for uploading brand-specific images such as logos, favicons, and banners.

HTML
<label class="form-label">شعار المنصة <span class="text-danger">*</span></label>
<label class="photo-uploader">
<input class="d-none" type="file">
<span class="photo-uploader__upload-area">
<span class="tticon-upload photo-uploader__icon"></span>
<span class="photo-uploader__content">
<span class="photo-uploader__text">أعلى: <span class="text-english">300 KB</span></span>
<span class="photo-uploader__text"><span class="text-english">300 KB</span></span>
</span>
</span>
<span class="photo-uploader__preview" style="background-image: url('./images/photo-placeholder.svg')"></span>
</label>
<!-- Usage Example -->
<BrandFileInput
v-model="logoImage"
label="صورة الشعار"
name="logo"
accepted-file-types="image/*"
required
/>
<!-- Vue Component Code Block -->
<template>
<label class="form-label">
{{ label }}
<span v-if="required" class="text-danger">*</span>
</label>
<label class="photo-uploader">
<input
ref="fileInputRef"
class="d-none"
type="file"
:name="name"
:accept="acceptedFileTypes"
@change="handleFileChange"
:required="required"
/>
<span class="photo-uploader__upload-area" @click="fileInputRef.click()">
<span class="tticon-upload photo-uploader__icon"></span>
<span class="photo-uploader__content">
<span class="photo-uploader__text">أعلى: <span class="text-english">300 KB</span></span>
<span class="photo-uploader__text"><span class="text-english">300 KB</span></span>
</span>
</span>
<span
class="photo-uploader__preview"
v-if="previewUrl"
:style="{ backgroundImage: `url('${previewUrl}')` }"
></span>
</label>
</template>
<script setup>
import { ref, computed, onBeforeUnmount } from 'vue'
const props = defineProps({
modelValue: [File, String],
label: String,
name: String,
acceptedFileTypes: String,
required: Boolean,
})
const emit = defineEmits(['update:modelValue'])
const fileInputRef = ref(null)
// Holds a generated preview URL if modelValue is a File
const previewBlobUrl = ref('')
// Function to create and revoke object URL
function createAndRevokeObjectUrl(file) {
if (previewBlobUrl.value) URL.revokeObjectURL(previewBlobUrl.value)
return URL.createObjectURL(file)
}
// Computes the actual preview (whether it's a file blob or a string URL)
const previewUrl = computed(() => {
if (props.modelValue instanceof File) {
return createAndRevokeObjectUrl(props.modelValue)
}
return props.modelValue // treat as string URL
})
// Clean up when unmounting
onBeforeUnmount(() => {
if (previewBlobUrl.value) URL.revokeObjectURL(previewBlobUrl.value)
})
function handleFileChange(event) {
const file = event.target.files[0]
if (!file) return
emit('update:modelValue', file)
// Reset file input to allow same file re-selection
event.target.value = null
}
</script>
Profile Picture Upload
A specialized input field for uploading user avatars when creating or updating profiles.

HTML
<label class="upload-avatar-button mx-auto mb-3">
<input class="d-none" type="file">
<span class="tticon-camera"></span>
</label>
<!-- Usage Example -->
<ProfilePictureFileInput
v-model="profileImage"
label="صورة الملف الشخصي"
name="profile"
accepted-file-types="image/*"
/>
<!-- Vue Component Code Block -->
<template>
<label
class="upload-avatar-button mx-auto mb-3"
:style="{ backgroundImage: `url('${previewUrl}')` }"
@click="fileInputRef.click()"
>
<input
ref="fileInputRef"
class="d-none"
type="file"
:name="name"
:accept="acceptedFileTypes"
@change="handleFileChange"
/>
<span class="tticon-camera" :style="previewUrl ? { display: 'none' } : {}"></span>
</label>
</template>
<script setup>
import { ref, computed, onBeforeUnmount } from 'vue'
const props = defineProps({
modelValue: [File, String],
name: String,
acceptedFileTypes: String,
required: Boolean,
})
const emit = defineEmits(['update:modelValue'])
const fileInputRef = ref(null)
// Holds a generated preview URL if modelValue is a File
const previewBlobUrl = ref('')
// Function to create and revoke object URL
function createAndRevokeObjectUrl(file) {
if (previewBlobUrl.value) URL.revokeObjectURL(previewBlobUrl.value)
return URL.createObjectURL(file)
}
// Computes the actual preview (whether it's a file blob or a string URL)
const previewUrl = computed(() => {
if (props.modelValue instanceof File) {
return createAndRevokeObjectUrl(props.modelValue)
}
return props.modelValue // treat as string URL
})
// Clean up when unmounting
onBeforeUnmount(() => {
if (previewBlobUrl.value) URL.revokeObjectURL(previewBlobUrl.value)
})
function handleFileChange(event) {
const file = event.target.files[0]
if (!file) return
emit('update:modelValue', file)
// Reset file input to allow same file re-selection
event.target.value = null
}
</script>