3

I want to upload some file, but I can't access with v-model

VueCompilerError: v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.

So, I've change the v-model to v-on:change like code below, but I don't know how to do this

<input
  type="file"
  name="file"
  v-on:change="uploadFile"
  style="display: none; border: none"
/>

I read a big list of examples, but none worked.

My data (Idk if it's right):

data() {
  return {
    file: null as unknown as File,
  };
},

4 Answers 4

4

A basic example could look like this

<input type="file" @change="onFileChange">

JavaScript version

methods: {
  onFileChange(event) {
    let files = event.target.files || event.dataTransfer.files;
    if (!files.length) return;

    doSomethingWithTheFile(files[0]);
  },
}

TypeScript version could look like this

interface HTMLInputEvent extends Event {
  target: HTMLInputElement & EventTarget
}


methods: {
  onFileChange(event: HTMLInputEvent | DragEvent) {
    let files =
      (event as HTMLInputEvent).target.files ||
      (event as DragEvent).dataTransfer.files
    if (!files.length) return

    doSomethingWithTheFile(files[0])
  },
},
Sign up to request clarification or add additional context in comments.

3 Comments

typescript return a lot of error because Idk who is e and files? what is the file type is File?
I have added a TypeScript version @ThiagoValente
@Freeman interface example exists for HTMLInputEvent, just above the methods
3

What does your uploadFile look like?

The simpler may be to declare it to take directly the files list:

async uploadFiles(fileList: Array<File>) {
    for (const file of fileList) {
        // do something with the file

And call it this way:

v-on:change="uploadFiles($event.target.files)"

Comments

0

For vue3js we would get the following typescript setup:

<script setup lang="ts">  
interface HTMLInputEvent extends Event {
  target: HTMLInputElement & EventTarget;
}

const fileChanged = (ev: HTMLInputEvent | DragEvent) => {
  let files = (ev as HTMLInputEvent).target.files || (ev as DragEvent).dataTransfer?.files;
  if (!files?.length) return;

  doSomethingWithTheFile(files[0]);
};
</script>

Comments

0

It looks like you're working on uploading files in Vue.js. Instead of using v-model, which doesn't work for file inputs, you're using v-on: change, which is the right approach. Keep it up!

 <input
      type="file"
      name="file"
      @change="uploadFile"
      style="display: none; border: none"
  />

And in your javascript Vue component:

export default {
  data() {
    return {
      file: null,
    };
  },
  methods: {
    uploadFile(event) {
      const files = event.target.files;
      
      if (files.length > 0) {
        this.file = files[0];
        console.log("Uploaded file:", this.file);
        // Implement your upload logic here
      }
    },
  },
};

Typescript version:

export default {
  data() {
    return {
      file: null as File | null,
    };
  },
  methods: {
    uploadFile(event: Event) {
      const target = event.target as HTMLInputElement;
      const files = target.files;
      
      if (files && files.length > 0) {
        this.file = files[0];
        console.log("Uploaded file:", this.file);
        // Implement your upload logic here
      }
    },
  },
};

In the TypeScript version, we add type annotations for the file property and the event parameter in the uploadFile method. Additionally, we use type assertions to handle the types more explicitly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.