Let's say I have a main Vue instance that has child components. Is there a way of calling a method belonging to one of these components from outside the Vue instance entirely?
Here is an example:
var vm = new Vue({_x000D_
el: '#app',_x000D_
components: {_x000D_
'my-component': { _x000D_
template: '#my-template',_x000D_
data: function() {_x000D_
return {_x000D_
count: 1,_x000D_
};_x000D_
},_x000D_
methods: {_x000D_
increaseCount: function() {_x000D_
this.count++;_x000D_
}_x000D_
}_x000D_
},_x000D_
}_x000D_
});_x000D_
_x000D_
$('#external-button').click(function()_x000D_
{_x000D_
vm['my-component'].increaseCount(); // This doesn't work_x000D_
});
_x000D_
<script src="http://vuejs.org/js/vue.js"></script>_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<div id="app">_x000D_
_x000D_
<my-component></my-component>_x000D_
<br>_x000D_
<button id="external-button">External Button</button>_x000D_
</div>_x000D_
_x000D_
<template id="my-template">_x000D_
<div style="border: 1px solid; padding: 5px;">_x000D_
<p>A counter: {{ count }}</p>_x000D_
<button @click="increaseCount">Internal Button</button>_x000D_
</div>_x000D_
</template>
_x000D_
So when I click the internal button, the increaseCount()
method is bound to its click event so it gets called. There is no way to bind the event to the external button, whose click event I am listening for with jQuery, so I'll need some other way to call increaseCount
.
EDIT
It seems this works:
vm.$children[0].increaseCount();
However, this is not a good solution because I am referencing the component by its index in the children array, and with many components this is unlikely to stay constant and the code is less readable.
This question is related to
javascript
vue.js
You can use Vue event system
vm.$broadcast('event-name', args)
and
vm.$on('event-name', function())
Here is the fiddle: http://jsfiddle.net/hfalucas/wc1gg5v4/59/
Say you have a child_method()
in the child component:
export default {
methods: {
child_method () {
console.log('I got clicked')
}
}
}
Now you want to execute the child_method
from parent component:
<template>
<div>
<button @click="exec">Execute child component</button>
<child-cmp ref="child"></child_cmp> <!-- note the ref="child" here -->
</div>
</template>
export default {
methods: {
exec () { //accessing the child component instance through $refs
this.$refs.child.child_method() //execute the method belongs to the child component
}
}
}
If you want to execute a parent component method from child component:
this.$parent.name_of_method()
NOTE: It is not recommended to access the child and parent component like this.
Instead as best practice use Props & Events for parent-child communication.
If you want communication between components surely use vuex or event bus
Please read this very helpful article
A slightly different (simpler) version of the accepted answer:
Have a component registered on the parent instance:
export default {
components: { 'my-component': myComponent }
}
Render the component in template/html with a reference:
<my-component ref="foo"></my-component>
Access the component method:
<script>
this.$refs.foo.doSomething();
</script>
This is a simple way to access a component's methods from other component
// This is external shared (reusable) component, so you can call its methods from other components
export default {
name: 'SharedBase',
methods: {
fetchLocalData: function(module, page){
// .....fetches some data
return { jsonData }
}
}
}
// This is your component where you can call SharedBased component's method(s)
import SharedBase from '[your path to component]';
var sections = [];
export default {
name: 'History',
created: function(){
this.sections = SharedBase.methods['fetchLocalData']('intro', 'history');
}
}
Here is a simple one
this.$children[indexOfComponent].childsMethodName();
For Vue2 this applies:
var bus = new Vue()
// in component A's method
bus.$emit('id-selected', 1)
// in component B's created hook
bus.$on('id-selected', function (id) {
// ...
})
See here for the Vue docs. And here is more detail on how to set up this event bus exactly.
If you'd like more info on when to use properties, events and/ or centralized state management see this article.
See below comment of Thomas regarding Vue 3.
Sometimes you want to keep these things contained within your component. Depending on DOM state (the elements you're listening on must exist in DOM when your Vue component is instantiated), you can listen to events on elements outside of your component from within your Vue component. Let's say there is an element outside of your component, and when the user clicks it, you want your component to respond.
In html you have:
<a href="#" id="outsideLink">Launch the component</a>
...
<my-component></my-component>
In your Vue component:
methods() {
doSomething() {
// do something
}
},
created() {
document.getElementById('outsideLink').addEventListener('click', evt =>
{
this.doSomething();
});
}
I am not sure is it the right way but this one works for me.
First import the component which contains the method you want to call in your component
import myComponent from './MyComponent'
and then call any method of MyCompenent
myComponent.methods.doSomething()
You can set ref for child components then in parent can call via $refs:
Add ref to child component:
<my-component ref="childref"></my-component>
Add click event to parent:
<button id="external-button" @click="$refs.childref.increaseCount()">External Button</button>
var vm = new Vue({_x000D_
el: '#app',_x000D_
components: {_x000D_
'my-component': { _x000D_
template: '#my-template',_x000D_
data: function() {_x000D_
return {_x000D_
count: 1,_x000D_
};_x000D_
},_x000D_
methods: {_x000D_
increaseCount: function() {_x000D_
this.count++;_x000D_
}_x000D_
}_x000D_
},_x000D_
}_x000D_
});
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>_x000D_
<div id="app">_x000D_
_x000D_
<my-component ref="childref"></my-component>_x000D_
<button id="external-button" @click="$refs.childref.increaseCount()">External Button</button>_x000D_
</div>_x000D_
_x000D_
<template id="my-template">_x000D_
<div style="border: 1px solid; padding: 2px;" ref="childref">_x000D_
<p>A counter: {{ count }}</p>_x000D_
<button @click="increaseCount">Internal Button</button>_x000D_
</div>_x000D_
</template>
_x000D_
Using Vue 3:
const app = createApp({})
// register an options object
app.component('my-component', {
/* ... */
})
....
// retrieve a registered component
const MyComponent = app.component('my-component')
MyComponent.methods.greet();
I have used a very simple solution. I have included a HTML element, that calls the method, in my Vue Component that I select, using Vanilla JS, and I trigger click!
In the Vue Component, I have included something like the following:
<span data-id="btnReload" @click="fetchTaskList()"><i class="fa fa-refresh"></i></span>
That I use using Vanilla JS:
const btnReload = document.querySelector('[data-id="btnReload"]');
btnReload.click();
Source: Stackoverflow.com