DEV Community

shunnNet
shunnNet

Posted on

Handling input file in Vue

The official Vue documentation does not explicitly mention how to handle input files.

If you search for "vue input file" you will find many answers like this:

<script setup>
import { shallowRef, ref } from "vue"
const inputRef = shallowRef()
const files = ref([])
const onChange = (e) => {
  files.value = e.target.files
}
const clear = () => {
  inputRef.value.value = ''
  files.value = []
}
</script>

<template>
  <input ref="inputRef" type="file" multiple @change="onChange" />
  <button @click="clear">Clear</button>
</template>
Enter fullscreen mode Exit fullscreen mode

Because you cannot directly set the value of the input file, you cannot use v-model too.

.files

In addition to inputFile.value, you can also use inputFile.files to access the value of the input file.

inputFile.files // FileList
Enter fullscreen mode Exit fullscreen mode

.value is almost read-only (can only be programmatically reset). But .files can be set using FileList. You can assign it a FileList object. For example, you can place the files from inputFile1 into inputFile2's files.

const files = inputFile1.files

inputFile2.files = files
Enter fullscreen mode Exit fullscreen mode

In other words, we can set value of input file using javascript.

v-bind dom properties

This feature of Vue might be a bit obscure? Because even after playing with Vue for several years, it's my first time encountering this functionality, and I've found that it's been supported since Vue 2.

The v-bind syntax supports setting DOM properties.

In Vue 3, when you use v-bind on an HTML tag and the attribute is not a standard HTML attribute, Vue will use the in operator to determine if it's a property of the DOM element. You can check v-bind document

Combining with the feature of .files property, we can make a more controllable input file.

<script setup>
import { shallowRef, ref } from "vue"
const files = ref()
const onChange = (e) => {
  files.value = e.target.files
}
const clear = () => {
  files.value = new DataTransfer().files // fill in a empty FileList
}
</script>

<template>
  <input 
    type="file" 
    multiple 
    :files="files" 
    @change="onChange" 
  />
  <button @click="clear">Clear</button>
</template>
Enter fullscreen mode Exit fullscreen mode

You can check live example here: https://stackblitz.com/edit/vitejs-vite-n16j6w?embed=1&file=src%2FApp.vue

Reference

Top comments (0)