Joel Rodrigues
Joel Rodrigues

Reputation: 58

Call method from another vue.js component through this.$refs

I have a sibling element which i want to trigger.

i've try this solution

<b-img @click="callFileLoader"/>
<b-file type="file" ref="fileUploader"></b-file>
...

methods:{
  callFileLoader () {
    this.$refs.fileUploader.click()
  }
} 

Got: Uncaught TypeError: this.$refs.fileUploader.click is not a function

b-file documentation

Upvotes: 1

Views: 3529

Answers (2)

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

After some debugging i found a way to access that input using this statement :

   this.$refs.fileUploader.$el.firstChild

which is <input> element that could be clickable.

new Vue({
  el: "#app",
  data() {
    return {
      file: null,
      file2: null
    }
  },
  methods: {
    callFileLoader() {

      this.$refs.fileUploader.$el.firstChild.click();

    }
  }

});
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/[email protected]/dist/bootstrap-vue.css" />

<div id='app'>

  <div>
    <!-- Styled -->

    <b-file v-model="file" ref="fileUploader" :state="Boolean(file)" placeholder="Choose a file..."></b-file>
    <div class="mt-3">Selected file: {{file && file.name}}</div>
    <button class="btn btn-primary" @click="callFileLoader">load</button>
  </div>
</div>

Upvotes: 2

Nikola Kirincic
Nikola Kirincic

Reputation: 3757

If it is sibling component, it is not recognized in sibling component via v-ref approach. Either try to access it via parent component or Vue root, if there is no parent component where it is nested:

 this.$root.$refs.fileUploader.click()

Or use this.$root.$emit() in sibling component b-img, to trigger event, and place event listener in events of b-file component to catch emited event and trigger click

so in b-img would be:

methods:{
  callFileLoader () {
    this.$root.$emit('file-uploader-click');
  }
} 

and in b-file would be:

events:{
  'file-uploader-click' : function() {
    this.click();
  }
} 

Instead of placing events method, you try to place v-on:event-name="action" within an component:

VueTools chrome extension is very useful to check correct reference name generated by VueJs

Upvotes: 1

Related Questions