DEV Community

Alan Schio
Alan Schio

Posted on • Updated on

Vue and Input File - Clear File or Select same file

Have you ever had the case where ou have a file selector component, you clear the file model but then you can't select the same file again?
File selection
Codepen: https://codepen.io/schirrel/pen/YzRGrvq

Well its kinda hard and curious to explain.
First of all to the TL/DR:
You need to use Vue's $refs and set the input to null.

Now if you want to understand why, let's pass thru some important stuff:

First: Vue doesn't work with v-model and file input, even has a discussion about it on the offical Vue's repo: Discussion.

Now lets undestand why doesnt work, two main things:

  1. input with type="file" only triggers change event, while v-model listen to input event.
  2. v-model needs to set the value html attribute, if you ever try to do :value="myFileModel" this error will show up:

Error in nextTick: "InvalidStateError: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

So with this comes a question: how to a clear a file, and most important, how make it possible to select again?

Lets paint a simple use case: You have your own file wrapper the uses a file input (obviously) but you save the file on the data. Example:

<template>
 <label for="inputFile">
      Click here to select you file
      <input type="file" name="inputFile" id="inputFile" @change="selectFile" />
    </label>
    <span v-if="file">
      File Selected {{ file.name }}
      <button @click="clearFile">remove</button>
    </span>
</template>
<script>
export default {
  data() {
    return {
      file: null
    };
  },
  methods: {
    selectFile(event) {
      this.file = event.target.files[0];
    },
    clearFile() {
      this.file = null;
    }
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

Even if clearFile is setting file as null, when selecting the file again the @change wont be triggered again. Thats why because the html value attribute still the same, the file prop on data doesn't affect it. Take a look at the codepen example.

Once we have seen that :value don't work with files, the proper way to do this is acessing the HTML <input type="file" /> and reset this value programmatically.

By adding a ref="fileInput" to the <input> and inside the clearFile method add:

this.$refs.fileInput.value = null
Enter fullscreen mode Exit fullscreen mode

Now it works:

Vue select same file

The codepen final solution: https://codepen.io/schirrel/pen/XWyjeOw

Note: this is common behavior across frameworks;

Top comments (1)

Collapse
 
gabrielaschlemper profile image
Gabriela Schlemper

thanks for that!