<template> <AppDoc name="FileUploadDemo" :sources="sources"> <h5>Import via Module</h5> <pre v-code.script><code> import FileUpload from 'primevue/fileupload'; </code></pre> <h5>Import via CDN</h5> <pre v-code><code> <script src="https://unpkg.com/primevue@^3/core/core.min.js"></script> <script src="https://unpkg.com/primevue@^3/fileupload/fileupload.min.js"></script> </code></pre> <h5>Getting Started</h5> <p>FileUpload requires a <i>url</i> property as the upload target and a <i>name</i> to identify the files at backend.</p> <pre v-code><code> <FileUpload name="demo[]" url="./upload" /> </code></pre> <h5>Multiple Uploads</h5> <p>Only one file can be selected at a time by default, to allow selecting multiple files at once enable <i>multiple</i> option.</p> <pre v-code><code> <FileUpload name="demo[]" url="./upload" :multiple="true" /> </code></pre> <h5>Basic UI</h5> <p>FileUpload basic mode provides a simpler UI as an alternative to advanced mode.</p> <pre v-code><code> <FileUpload mode="basic" name="demo[]" url="./upload" /> </code></pre> <h5>DragDrop</h5> <p>File selection can also be done by dragging and dropping from the filesystem to the content section of the component.</p> <h5>Auto Uploads</h5> <p>When <i>auto</i> property is enabled, upload begins as soon as file selection is completed or a file is dropped on the drop area.</p> <pre v-code><code> <FileUpload mode="basic" name="demo[]" url="./upload" :auto="true" /> </code></pre> <h5>File Types</h5> <p>Selectable file types can be restricted with <i>accept</i> property, example below only allows images to be uploaded. Read more about other possible values <a href="https://www.w3schools.com/tags/att_input_accept.asp"> here</a>.</p> <pre v-code><code> <FileUpload mode="basic" name="demo[]" url="./upload" accept="image/*" /> </code></pre> <h5>File Size and File Limit</h5> <p>Maximium file size can be restricted using <i>maxFileSize</i> property defined in bytes. Similarly <i>fileLimit</i> is available to restrict the number of files to be uploaded.</p> <pre v-code><code> <FileUpload name="demo[]" url="./upload" :maxFileSize="1000000" :fileLimit="3" /> </code></pre> <p>In order to customize the default messages use <i>invalidFileSizeMessage</i> and <i>invalidFileLimitMessage</i> options where {0} placeholder refers to the filename and {1} the file size.</p> <ul> <li>invalidFileSizeMessage: '{0}: Invalid file size, file size should be smaller than {1}.'</li> <li>invalidFileLimitMessage: 'Maximum number of files exceeded, limit is {0} at most.'</li> </ul> <h5>Request Customization</h5> <p>XHR request to upload the files can be customized using the before-upload callback that passes the xhr instance and FormData object as event parameters.</p> <h5>Custom Upload</h5> <p>Uploading implementation can be overridden by enabling <i>customMode</i> property and defining a custom upload handler event.</p> <pre v-code><code> <FileUpload name="demo[]" :customUpload="true" @uploader="myUploader" /> </code></pre> <pre v-code.script><code> myUploader(event) { //event.files == files to upload } </code></pre> <h5>Templating</h5> <p>FileUpload component is extremely customizable thanks to the templating features, both the <i>header</i> and <i>content</i> sections provide custom slots.</p> <pre v-code><code> <FileUpload name="demo[]" url="./upload.php" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <div class="flex flex-wrap justify-content-between align-items-center flex-1 gap-2"> <div class="flex gap-2"> <Button @click="chooseCallback()" icon="pi pi-images" class="p-button-rounded"></Button> <Button @click="uploadCallback()" icon="pi pi-cloud-upload" class="p-button-rounded p-button-success" :disabled="!files || files.length === 0"></Button> <Button @click="clearCallback()" icon="pi pi-times" class="p-button-rounded p-button-danger" :disabled="!files || files.length === 0"></Button> </div> <ProgressBar :value="totalSizePercent" :showValue="false" :class="['md:w-20rem h-1rem w-full md:ml-auto', {'exceeded-progress-bar': (totalSizePercent > 100)}]"><span class="white-space-nowrap">{{ totalSize }}B / 1Mb</span></ProgressBar> </div> </template> <template #content="{ files, uploadedFiles, onUploadedFileRemove, onFileRemove }"> <div v-if="files.length > 0"> <h5>Pending</h5> <div class="flex flex-wrap p-5 gap-5"> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" height="50" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <Badge value="Pending" severity="warning" /> <Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, onFileRemove, index)" class="p-button-outlined p-button-danger p-button-rounded" /> </div> </div> </div> <div v-if="uploadedFiles.length > 0"> <h5>Completed</h5> <div class="flex flex-wrap p-0 sm:p-5 gap-5"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <Badge value="Completed" class="mt-3" severity="success" /> <Button icon="pi pi-times" @click="onUploadedFileRemove(index)" class="p-button-outlined p-button-danger p-button-rounded" /> </div> </div> </div> </template> <template #empty> <div class="flex align-items-center justify-content-center flex-column"> <i class="pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400" /> <p class="mt-4 mb-0">Drag and drop files to here to upload.</p> </div> </template> </FileUpload> </code></pre> <h5>Properties</h5> <div class="doc-tablewrapper"> <table class="doc-table"> <thead> <tr> <th>Name</th> <th>Type</th> <th>Default</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>name</td> <td>string</td> <td>null</td> <td>Name of the request parameter to identify the files at backend.</td> </tr> <tr> <td>url</td> <td>string</td> <td>null</td> <td>Remote url to upload the files.</td> </tr> <tr> <td>mode</td> <td>string</td> <td>advanced</td> <td>Defines the UI of the component, possible values are "advanced" and "basic".</td> </tr> <tr> <td>multiple</td> <td>boolean</td> <td>false</td> <td>Used to select multiple files at once from file dialog.</td> </tr> <tr> <td>accept</td> <td>string</td> <td>null</td> <td>Pattern to restrict the allowed file types such as "image/*".</td> </tr> <tr> <td>disabled</td> <td>boolean</td> <td>false</td> <td>Disables the upload functionality.</td> </tr> <tr> <td>auto</td> <td>boolean</td> <td>false</td> <td>When enabled, upload begins automatically after selection is completed.</td> </tr> <tr> <td>maxFileSize</td> <td>number</td> <td>null</td> <td>Maximum file size allowed in bytes.</td> </tr> <tr> <td>invalidFileSizeMessage</td> <td>string</td> <td>"{0}: Invalid file size, file size should be smaller than {1}."</td> <td>Message of the invalid fize size.</td> </tr> <tr> <td>invalidFileLimitMessage</td> <td>string</td> <td>Maximum number of files exceeded, limit is {0} at most.</td> <td>Message to display when number of files to be uploaded exceeeds the limit.</td> </tr> <tr> <td>invalidFileTypeMessage</td> <td>string</td> <td>"{0}: Invalid file type, allowed file types: {1}"".</td> <td>Message of the invalid file type.</td> </tr> <tr> <td>fileLimit</td> <td>number</td> <td>null</td> <td>Maximum number of files that can be uploaded.</td> </tr> <tr> <td>withCredentials</td> <td>boolean</td> <td>false</td> <td>Cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates.</td> </tr> <tr> <td>previewWidth</td> <td>number</td> <td>50</td> <td>Width of the image thumbnail in pixels.</td> </tr> <tr> <td>chooseLabel</td> <td>string</td> <td>null</td> <td>Label of the choose button. Defaults to PrimeVue <router-link to="/locale">Locale</router-link> configuration.</td> </tr> <tr> <td>uploadLabel</td> <td>string</td> <td>Upload</td> <td>Label of the upload button. Defaults to PrimeVue <router-link to="/locale">Locale</router-link> configuration.</td> </tr> <tr> <td>cancelLabel</td> <td>string</td> <td>Cancel</td> <td>Label of the cancel button. Defaults to PrimeVue <router-link to="/locale">Locale</router-link> configuration.</td> </tr> <tr> <td>customUpload</td> <td>boolean</td> <td>false</td> <td>Whether to use the default upload or a manual implementation defined in uploadHandler callback. Defaults to PrimeVue <router-link to="/locale">Locale</router-link> configuration.</td> </tr> <tr> <td>showUploadButton</td> <td>boolean</td> <td>true</td> <td>Whether to show the upload button.</td> </tr> <tr> <td>showCancelButton</td> <td>boolean</td> <td>true</td> <td>Whether to show the cancel button.</td> </tr> <tr> <td>chooseIcon</td> <td>string</td> <td>pi pi-plus</td> <td>Icon of the choose button.</td> </tr> <tr> <td>uploadIcon</td> <td>string</td> <td>pi pi-upload</td> <td>Icon of the upload button.</td> </tr> <tr> <td>cancelIcon</td> <td>string</td> <td>pi pi-times</td> <td>Icon of the cancel button.</td> </tr> <tr> <td>style</td> <td>any</td> <td>null</td> <td>Inline style of the component.</td> </tr> <tr> <td>class</td> <td>string</td> <td>null</td> <td>Style class of the component.</td> </tr> </tbody> </table> </div> <h5>Events</h5> <div classe="doc-tablewrapper"> <table class="doc-table"> <thead> <tr> <th>Name</th> <th>Parameters</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>before-upload</td> <td> event.xhr: XmlHttpRequest instance. <br /> event.formData: FormData object. </td> <td>Callback to invoke before file upload begins to customize the request such as post parameters before the files.</td> </tr> <tr> <td>before-send</td> <td> event.xhr: XmlHttpRequest instance. <br /> event.formData: FormData object. </td> <td>Callback to invoke before file send begins to customize the request such as adding headers.</td> </tr> <tr> <td>upload</td> <td> event.xhr: XmlHttpRequest instance.<br /> event.files: Uploaded files. </td> <td>Callback to invoke when file upload is complete.</td> </tr> <tr> <td>error</td> <td> event.xhr: XmlHttpRequest instance.<br /> event.files: Files that are not uploaded. </td> <td>Callback to invoke if file upload fails.</td> </tr> <tr> <td>clear</td> <td>-.</td> <td>Callback to invoke when files in queue are removed without uploading.</td> </tr> <tr> <td>select</td> <td> event.originalEvent: Original browser event. <br /> event.files: List of selected files. </td> <td>Callback to invoke when files are selected.</td> </tr> <tr> <td>progress</td> <td> event.originalEvent: Original browser event. <br /> event.progress: Calculated progress value. </td> <td>Callback to invoke when files are being uploaded.</td> </tr> <tr> <td>uploader</td> <td>event.files: List of selected files.</td> <td>Callback to invoke to implement a custom upload.</td> </tr> <tr> <td>remove</td> <td> event.file: Removed file. <br /> event.files: Remaining files to be uploaded. </td> <td>Callback to invoke when a single file is removed from the file list to upload.</td> </tr> <tr> <td>removeUploadedFile</td> <td> event.file: Removed uploaded file. <br /> event.files: Remaining uploaded files. </td> <td>Callback to invoke when a single uploaded file is removed from the uploaded file list.</td> </tr> </tbody> </table> </div> <h5>Slots</h5> <div class="doc-tablewrapper"> <table class="doc-table"> <thead> <tr> <th>Name</th> <th>Parameters</th> </tr> </thead> <tbody> <tr> <td>header</td> <td> files: Files to upload <br /> uploadedFiles: Uploaded Files <br /> chooseCallback: Choose function <br /> uploadCallback: Upload function <br /> clearCallback: Clear function </td> </tr> <tr> <td>content</td> <td> files: Files to upload <br /> uploadedFiles: Uploaded Files <br /> progress: Uploaded progress as number <br /> messages: Status messages about upload process <br /> removeFileCallback(index): Function to remove a file <br /> removeUploadedFileCallback(index): Function to remove an uploaded file </td> </tr> <tr> <td>empty</td> <td>-</td> </tr> </tbody> </table> </div> <h5>Styling</h5> <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> <div class="doc-tablewrapper"> <table class="doc-table"> <thead> <tr> <th>Name</th> <th>Element</th> </tr> </thead> <tbody> <tr> <td>p-fileupload</td> <td>Container element.</td> </tr> <tr> <td>p-fileupload-basic</td> <td>Container element in basic mode.</td> </tr> <tr> <td>p-fileupload-advanced</td> <td>Container element in advanced mode.</td> </tr> <tr> <td>p-fileupload-buttonbar</td> <td>Header containing the buttons.</td> </tr> <tr> <td>p-fileupload-content</td> <td>Content section.</td> </tr> <tr> <td>p-fileupload-file</td> <td>File item.</td> </tr> <tr> <td>p-fileupload-file-thumbnail</td> <td>Image preview of a file.</td> </tr> <tr> <td>p-fileupload-file-details</td> <td>Container of file details.</td> </tr> <tr> <td>p-fileupload-file-name</td> <td>File name element.</td> </tr> <tr> <td>p-fileupload-file-size</td> <td>File size element.</td> </tr> <tr> <td>p-fileupload-file-badge</td> <td>File badge element.</td> </tr> <tr> <td>p-fileupload-file-actions</td> <td>Container of file actions.</td> </tr> <tr> <td>p-fileupload-file-remove</td> <td>Button to remove a file.</td> </tr> <tr> <td>p-fileupload-empty</td> <td>Container of the empty slot.</td> </tr> </tbody> </table> </div> <h5>Dependencies</h5> <p>None.</p> </AppDoc> </template> <script> export default { data() { return { sources: { 'options-api': { tabName: 'Options API Source', content: ` <template> <div> <Toast /> <h5>Advanced</h5> <FileUpload name="demo[]" url="https://www.primefaces.org/upload.php" @upload="onAdvancedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000"> <template #content> <ul v-if="uploadedFiles && uploadedFiles[0]"> <li v-for="file of uploadedFiles[0]" :key="file">{{ file.name }} - {{ file.size }} bytes</li> </ul> </template> <template #empty> <p>Drag and drop files to here to upload.</p> </template> </FileUpload> <h5>Templating</h5> <FileUpload name="demo[]" url="./upload.php" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <div class="flex flex-wrap justify-content-between align-items-center flex-1 gap-2"> <div class="flex gap-2"> <Button @click="chooseCallback()" icon="pi pi-images" class="p-button-rounded"></Button> <Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" class="p-button-rounded p-button-success" :disabled="!files || files.length === 0"></Button> <Button @click="clearCallback()" icon="pi pi-times" class="p-button-rounded p-button-danger" :disabled="!files || files.length === 0"></Button> </div> <ProgressBar :value="totalSizePercent" :showValue="false" :class="['md:w-20rem h-1rem w-full md:ml-auto', {'exceeded-progress-bar': (totalSizePercent > 100)}]"><span class="white-space-nowrap">{{ totalSize }}B / 1Mb</span></ProgressBar> </div> </template> <template #content="{ files, uploadedFiles, removeUploadedFileCallback, fileRemoveCallback }"> <div v-if="files.length > 0"> <h5>Pending</h5> <div class="flex flex-wrap p-5 gap-5"> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <Badge value="Pending" severity="warning" /> <Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, fileRemoveCallback, index)" class="p-button-outlined p-button-danger p-button-rounded" /> </div> </div> </div> <div v-if="uploadedFiles.length > 0"> <h5>Completed</h5> <div class="flex flex-wrap p-0 sm:p-5 sm:p-5 gap-5"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <Badge value="Completed" class="mt-3" severity="success" /> <Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" class="p-button-outlined p-button-danger p-button-rounded" /> </div> </div> </div> </template> <template #empty> <div class="flex align-items-center justify-content-center flex-column"> <i class="pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400" /> <p class="mt-4 mb-0">Drag and drop files to here to upload.</p> </div> </template> </FileUpload> <h5>Basic</h5> <FileUpload mode="basic" name="demo[]" url="./upload.php" accept="image/*" :maxFileSize="1000000" @upload="onUpload" /> <h5>Basic with Auto</h5> <FileUpload mode="basic" name="demo[]" url="./upload.php" accept="image/*" :maxFileSize="1000000" @upload="onUpload" :auto="true" chooseLabel="Browse" /> </div> </template> <script> export default { data() { return { uploadedFiles: [], files: [], totalSize: 0, totalSizePercent: 0 }; }, methods: { onRemoveTemplatingFile(file, onFileRemove, index) { onFileRemove(index); this.totalSize -= parseInt(this.formatSize(file.size)); this.totalSizePercent = this.totalSize / 10; }, onClearTemplatingUpload(clear) { clear(); this.totalSize = 0; this.totalSizePercent = 0; }, onSelectedFiles(event) { this.files = event.files; this.files.forEach((file) => { this.totalSize += parseInt(this.formatSize(file.size)); }); }, onAdvancedUpload() { this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); }, uploadEvent(callback) { this.totalSizePercent = this.totalSize / 10; callback(); }, onTemplatedUpload() { this.totalSize = 0; this.totalSizePercent = 0; this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); }, onUpload() { this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); }, formatSize(bytes) { if (bytes === 0) { return '0 B'; } let k = 1000, dm = 3, sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } } }; <\\/script> <style lang="scss" scoped> ::v-deep(.custom-progress-bar) { .p-progressbar-value { background-color: #f44336; } } </style> ` }, 'composition-api': { tabName: 'Composition API Source', content: ` <template> <div> <Toast /> <h5>Advanced</h5> <FileUpload name="demo[]" url="https://www.primefaces.org/upload.php" @upload="onAdvancedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000"> <template #content> <ul v-if="uploadedFiles && uploadedFiles[0]"> <li v-for="file of uploadedFiles[0]" :key="file">{{ file.name }} - {{ file.size }} bytes</li> </ul> </template> <template #empty> <p>Drag and drop files to here to upload.</p> </template> </FileUpload> <h5>Templating</h5> <FileUpload name="demo[]" url="./upload.php" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <div class="flex flex-wrap justify-content-between align-items-center flex-1 gap-2"> <div class="flex gap-2"> <Button @click="chooseCallback()" icon="pi pi-images" class="p-button-rounded"></Button> <Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" class="p-button-rounded p-button-success" :disabled="!files || files.length === 0"></Button> <Button @click="clearCallback()" icon="pi pi-times" class="p-button-rounded p-button-danger" :disabled="!files || files.length === 0"></Button> </div> <ProgressBar :value="totalSizePercent" :showValue="false" :class="['md:w-20rem h-1rem w-full md:ml-auto', {'exceeded-progress-bar': (totalSizePercent > 100)}]"><span class="white-space-nowrap">{{ totalSize }}B / 1Mb</span></ProgressBar> </div> </template> <template #content="{ files, uploadedFiles, removeUploadedFileCallback, fileRemoveCallback }"> <div v-if="files.length > 0"> <h5>Pending</h5> <div class="flex flex-wrap p-0 sm:p-5 gap-5"> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <Badge value="Pending" severity="warning" /> <Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, fileRemoveCallback, index)" class="p-button-outlined p-button-danger p-button-rounded" /> </div> </div> </div> <div v-if="uploadedFiles.length > 0"> <h5>Completed</h5> <div class="flex flex-wrap p-0 sm:p-5 gap-5"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <Badge value="Completed" class="mt-3" severity="success" /> <Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" class="p-button-outlined p-button-danger p-button-rounded" /> </div> </div> </div> </template> <template #empty> <div class="flex align-items-center justify-content-center flex-column"> <i class="pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400" /> <p class="mt-4 mb-0">Drag and drop files to here to upload.</p> </div> </template> </FileUpload> <h5>Basic</h5> <FileUpload mode="basic" name="demo[]" url="./upload.php" accept="image/*" :maxFileSize="1000000" @upload="onUpload" /> <h5>Basic with Auto</h5> <FileUpload mode="basic" name="demo[]" url="./upload.php" accept="image/*" :maxFileSize="1000000" @upload="onUpload" :auto="true" chooseLabel="Browse" /> </div> </template> <script> import { ref } from 'vue'; import { useToast } from 'primevue/usetoast'; export default { setup() { const toast = useToast(); const uploadedFile = ref([]); const files = ref([]); const totalSize = ref(0); const totalSizePercent = ref(0); const onRemoveTemplatingFile = (file, onFileRemove, index) => { onFileRemove(index); totalSize.value -= parseInt(this.formatSize(file.size)); totalSizePercent.value = totalSize.value / 10; } const onClearTemplatingUpload = (clear) => { clear(); totalSize.value = 0; totalSizePercent.value = 0; } const onSelectedFiles = (event) => { files.value = event.files; files.value.forEach((file) => { totalSize.value += parseInt(this.formatSize(file.size)); }); } const onAdvancedUpload = () => { toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); } const uploadEvent = (callback) => { totalSizePercent.value = totalSize.value / 10; callback(); }, const onTemplatedUpload = () => { totalSize.value = 0; totalSizePercent.value = 0; toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); } const onUpload = () => { toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); } const formatSize = (bytes) => { if (bytes === 0) { return '0 B'; } let k = 1000, dm = 3, sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } return { onUpload, onRemoveTemplatingFile, onClearTemplatingUpload, onSelectedFiles, onAdvancedUpload, uploadEvent, onTemplatedUpload, onUpload, formatSize }; } } <\\/script> <style lang="scss" scoped> ::v-deep(.custom-progress-bar) { .p-progressbar-value { background-color: #f44336; } } </style> ` }, 'browser-source': { tabName: 'Browser Source', imports: `<script src="https://unpkg.com/primevue@^3/fileupload/fileupload.min.js"><\\/script> <script src="https://unpkg.com/primevue@^3/badge/badge.min.js"><\\/script> <script src="https://unpkg.com/primevue@^3/toast/toast.min.js"><\\/script> <script src="https://unpkg.com/primevue@^3/toastservice/toastservice.min.js"><\\/script>`, content: `<div id="app"> <p-toast></p-toast> <h5>Advanced</h5> <p-fileupload name="demo[]" url="https://www.primefaces.org/upload.php" @upload="onAdvancedUpload($event)" :multiple="true" accept="image/*" :max-file-size="1000000"> <template #content> <ul v-if="uploadedFiles && uploadedFiles[0]"> <li v-for="file of uploadedFiles[0]" :key="file">{{ file.name }} - {{ file.size }} bytes</li> </ul> </template> <template #empty> <p>Drag and drop files to here to upload.</p> </template> </p-fileupload> <h5>Templating</h5> <p-fileupload name="demo[]" url="./upload.php" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :max-file-size="1000000" @select="onSelectedFiles"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <div class="flex flex-wrap justify-content-between align-items-center flex-1 gap-2"> <div class="flex gap-2"> <p-button @click="chooseCallback()" icon="pi pi-images" class="p-button-rounded"></p-button> <p-button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" class="p-button-rounded p-button-success" :disabled="!files || files.length === 0"></p-button> <p-button @click="clearCallback()" icon="pi pi-times" class="p-button-rounded p-button-danger" :disabled="!files || files.length === 0"></p-button> </div> <p-progressbar :value="totalSizePercent" :show-value="false" :class="['md:w-20rem h-1rem w-full md:ml-auto', {'exceeded-progress-bar': (totalSizePercent > 100)}]"><span class="white-space-nowrap">{{ totalSize }}B / 1Mb</span></p-progressbar> </div> </template> <template #content="{ files, uploadedFiles, removeUploadedFileCallback, fileRemoveCallback }"> <div v-if="files.length > 0"> <h5>Pending</h5> <div class="flex flex-wrap p-0 sm:p-5 gap-5"> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <p-badge value="Pending" severity="warning"></p-badge> <p-button icon="pi pi-times" @click="onRemoveTemplatingFile(file, fileRemoveCallback, index)" class="p-button-outlined p-button-danger p-button-rounded"></p-button> </div> </div> </div> <div v-if="uploadedFiles.length > 0"> <h5>Completed</h5> <div class="flex flex-wrap p-0 sm:p-5 gap-5"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-6 flex flex-column border-1 surface-border align-items-center gap-3"> <div> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" class="shadow-2" /> </div> <span class="font-semibold">{{ file.name }}</span> <div>{{ formatSize(file.size) }}</div> <p-badge value="Completed" class="mt-3" severity="success"></p-badge> <p-button icon="pi pi-times" @click="removeUploadedFileCallback(index)" class="p-button-outlined p-button-danger p-button-rounded"></p-button> </div> </div> </div> </template> <template #empty> <div class="flex align-items-center justify-content-center flex-column"> <i class="pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400"></i> <p class="mt-4 mb-0">Drag and drop files to here to upload.</p> </div> </template> </p-fileupload> <h5>Basic</h5> <p-fileupload mode="basic" name="demo[]" url="./upload.php" accept="image/*" :max-file-size="1000000" @upload="onUpload"></p-fileupload> <h5>Basic with Auto</h5> <p-fileupload mode="basic" name="demo[]" url="./upload.php" accept="image/*" :max-file-size="1000000" @upload="onUpload" :auto="true" choose-label="Browse"></p-fileupload> </div> <script type="module"> const { createApp, ref } = Vue; const { useToast } = primevue.usetoast; const App = { setup() { const toast = useToast(); const uploadedFile = ref([]); const files = ref([]); const totalSize = ref(0); const totalSizePercent = ref(0); return {toast, uploadedFile,files,totalSize,totalSizePercent}; }, methods: { onRemoveTemplatingFile(file, fileRemoveCallback, index) { fileRemoveCallback(index); this.totalSize -= parseInt(this.formatSize(file.size)); this.totalSizePercent = this.totalSize / 10; }, onClearTemplatingUpload(clear) { clear(); this.totalSize = 0; this.totalSizePercent = 0; }, onSelectedFiles(event) { this.files = event.files; this.files.forEach((file) => { this.totalSize += parseInt(this.formatSize(file.size)); }); }, onAdvancedUpload() { this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); }, uploadEvent(callback) { this.totalSizePercent = this.totalSize / 10; callback(); }, onTemplatedUpload() { this.totalSize = 0; this.totalSizePercent = 0; this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); }, onUpload() { this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); }, formatSize(bytes) { if (bytes === 0) { return '0 B'; } let k = 1000, dm = 3, sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } }, components: { "p-fileupload": primevue.fileupload, "p-button": primevue.button, "p-badge": primevue.badge, "p-progressbar": primevue.progressbar, "p-toast": primevue.toast } }; const app = createApp(App) app.use(primevue.config.default) app.use(primevue.toastservice) app.mount("#app"); <\\/script> ` } } }; } }; </script>