10

I'm trying to bind a input file to a button using Vue.js
Having the following:

<input type="file hidden>
<button>Choose</button>

In JQuery would be somthing like:

$('button').click(function() {
    $('input[type=file]').click();
});

So, what this is doing is binding the click event on the button to the input file, this way I have complete control on the look of the button, it can even be a anchor or a image or any element to trigger the event to the input.

My question is: How can I accomplish this using Vue.js?

Thank you!

9 Answers 9

26

You can do this:

HTML:

<input id="fileUpload" type="file" hidden>
<button @click="chooseFiles()">Choose</button>

Vue.js:

methods: {
    chooseFiles: function() {
        document.getElementById("fileUpload").click()
    },
...

EDIT - Update syntax:

methods: {
    chooseFiles() {
        document.getElementById("fileUpload").click()
    },
...
Sign up to request clarification or add additional context in comments.

4 Comments

it's safer use component's $refs and avoid lookup by id
@farincz Could you explain why? The only difference would be to change the dependency from the element id to the ref attribute. i'm wondering if there is anything else. Thx.
@crabbly Using id is valid only for singleton components. Refs are need for components with multiple instances on page. Also reusable components / libraries should not spoil global id space (to avoid potential name clash).
Interesting. Thank you for the feedback. I believe that is our responsibility to not have multiple elements with the same ID under the global namespace. Therefore, the problem you describe shouldn't exist in the first place. Refs are a good option, specially on the scenario you have described, but it doesn't justify having duplicated element ids on the page. Element ids should be unique.
10

Add a ref="file" to your <input> element and later use $refs.file to access it.

<input ref="file" type="file">
<div @click="selectFile()">click to select a file</div>

methods:{
  selectFile(){
    let fileInputElement = this.$refs.file;
    fileInputElement.click();

    // Do something with chosen file 
  }
}

👌 Demo: https://codepen.io/Jossef/pen/QWEbNGv

Comments

8

Simplest way to do this is to stylize a label element like a button, HTML only.

Comments

6

you can use the label html tag for doing this like below

<label for="upload-file" class="css-class">
    <input type="file" id="upload-file" hidden @change="choosFile"/>
</label>

in this way you didn't need the button any more and you can customize the label with css as the way you like it

Comments

3

In Vue:

How code below works:

  1. Open file explorer on button (label) click;
  2. Select a file, continue;
  3. @onChange will detect new file:
<label>
  <button/> //this can be an icon, link,...
  <input @change="doSomething" type="file" ref="file" accept="image/gif, 
    image/jpeg, image/png" hidden/>
</label>
  1. Handle the file
doSomething(e: any) { 
  const file = e.target.files[0]
}

Comments

1

There is a much simpler way of way doing this using Vue 3

<input type="file" id="upload-file" name="upload-file" hidden>
<label for="upload-file" refs="upload-file" class="file-btn">Choose a file</label>

Using this you can add classes and styling to the label field.

Comments

1

This might help someone who is using coreui <CInputFile> tag.

for <CInputFile>, this.$refs.file.click() and this.$refs.file.$el.click() both doesn't work.

Because <CInputFile> wraps <div> around <input type="file">. so $el is actually a div element here, you need to go find the <input type="file"> tag and trigger the click() event on the <input type="file"> tag like this

this.$refs.file.$el.getElementsByTagName('input')[0].click().

Comments

0
<input ref="refName" type="file">
<div @click="selectFile()">Select file</div>
export default: {
   methods:{
      selectFile(){
        // refs return list of objects with name 'refName' or if only one object
        const r = this.$refs.refName[0] || this.$refs.refName;
        r.click();
     }
   }
}

Comments

0

When clicking the parent, it will click the ref upload (which is the child)

<div class="card card-upload" @click="$refs.upload.click()">
   <i class="fa fa-plus fa-lg"></i>
   <input ref="upload" type="file" hidden @change="upload">
</div>

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.