Skip to content

File Upload

Input elements with type "file" let the user choose one or more files from their device storage. Once chosen, the files can be uploaded to a server using form submission.

Examples

Input

Code
vue
<script setup lang="ts">
interface HTMLInputEvent extends Event {
  target: HTMLInputElement
}

const onUpload = (e: HTMLInputEvent) => {
  console.log(e.target.files)
}
</script>

<template>
  <base-file-upload @change="onUpload" />
</template>

Label

Code
vue
<script setup lang="ts">
interface HTMLInputEvent extends Event {
  target: HTMLInputElement
}

const onUpload = (e: HTMLInputEvent) => {
  console.log(e.target.files)
}
</script>

<template>
  <base-file-upload
    @change="onUpload"
    label="Label"
    description="Vertical Layout"
    layout="vertical"
  />
  <base-file-upload
    @change="onUpload"
    label="Label"
    description="Horizontal Layout"
    layout="horizontal"
  />
</template>

Helper

Code
vue
<script setup lang="ts">
import { ref } from 'vue'

interface HTMLInputEvent extends Event {
  target: HTMLInputElement
}

const onUpload = (e: HTMLInputEvent) => {
  console.log(e.target.files)
}

const errors = ref<string[]>(['Errors'])
</script>

<template>
  <base-file-upload @change="onUpload" label="Label" required />
  <base-file-upload @change="onUpload" label="Label" description="Description Example" />
  <base-file-upload @change="onUpload" label="Label" :helpers="['Helper Example']" />
  <base-file-upload @change="onUpload" label="Label" v-model:errors="errors" />
</template>

Slot

Code
vue
<script setup lang="ts">
import { ref } from 'vue'

interface HTMLInputEvent extends Event {
  target: HTMLInputElement
}

const files = ref()
const onUpload = (e: HTMLInputEvent) => {
  files.value = e.target.files
}
</script>

<template>
  <base-file-upload
    @change="onUpload"
    label="Label"
    description="Horizontal Layout"
    layout="horizontal"
  >
    <template v-slot="{ fileRef }">
      <base-button size="sm" @click="fileRef.click()">
        <base-icon icon="i-far-arrow-up-from-bracket" /> Choose File
      </base-button>
      <p class="ml-2" v-if="files">
        {{ files.length === 1 ? files[0].name : files.length + ' files' }}
      </p>
      <base-icon v-if="files" icon="i-far-xmark" class="ml-2 btn" @click="() => (files = null)" />
    </template>
  </base-file-upload>
</template>

File Upload API

Types

ts
export type BaseFileUploadBorderType = 'none' | 'simple' | 'full'
export type BaseFormLayoutType = 'vertical' | 'horizontal'

Props

NameTypeDefaultDescription
v-model:errorsstring[]Input error message.
idstringInput id.
labelstringInput label.
descriptionstringInput description.
borderBaseFileUploadBorderTypefullInput border.
layoutBaseFormLayoutTypeverticalInput layout.
acceptstringAccept mimetype.
multiplebooleanfalseUpload multiple files.
autofocusbooleanfalseFocus input on page load.
requiredbooleanfalseif true input is required.
disabledbooleanfalseif true input is disabled.
helpersstring[]Input helper message.
data-testidstringTesting ID.

Slot

#default slot for rendering custom file upload

Event

@change event for choosen file upload

Automated Test Guide

If you pass a data-testid to the <base-file-upload> component, it will automatically generate unique data-testid attributes for testing.

To test file uploads, place the test file in the cypress/fixtures directory:

bash
[root]
├── src
└── cypress
    ├── e2e
    └── fixtures
        └── image.png

Gherkin Scenario

txt
When I upload "image.png" into "file-upload"

Step Definition

ts
When('I upload {string} into {string}', (file: string, selector: string) => {
  cy.get(`[data-testid="${selector}"]`).attachFile(file)
})

NOTE

This step uses the cypress-file-upload plugin. Make sure it is installed and properly configured in your Cypress setup.

Code Implementation

vue
<script setup>
import { ref } from 'vue'

const file = ref()
</script>

<template>
  <base-file-upload v-model="file" data-testid="avatar" />
</template>

Released under the MIT License.