I have a Vue app like this:
<div id="example">
<event-emitting-component @clicked="methodOnRootInstance"></event-emitting-component>
<event-emitting-component-parent></event-emitting-component-parent>
<div v-for="click in clicks">
{{ click }}
</div>
</div>
And here is the JS for it:
// Child
Vue.component('event-emitting-component', {
template: '<div class="event-emitting-component" @click="$emit(\'clicked\')">Event emitter</div>'
});
// Parent
Vue.component('event-emitting-component-parent', {
template: '<div class="event-emitting-component-parent">' +
'A custom parent!'+
'<event-emitting-component></event-emitting-component>' + // <-- Please note child component
'</div>'
});
// create a root instance
new Vue({
el: '#example',
data: {
clicks : []
},
methods : {
methodOnRootInstance : function(){
this.clicks.push('Element clicked');
}
}
})
If you want to play with it it is also here:
https://codepen.io/EightArmsHQ/pen/QgbwPG?editors=1010
When you click the top child component a click is registered on the root element. Perfect.
When the child component is nested inside a parent (the second component in the example), obviously I can't add a @clicked="methodOnRootInstance"
as that method doesn't exist inside the component.
What is the best way to pass an event up through a number of nested components?
I've made a stripped back example here, but in reality some components are two or three levels deep. Is the answer (what I think it is) that inside the parent component I would have the following:
Vue.component('event-emitting-component-parent', {
template: '<div class="event-emitting-component-parent">' +
'A custom parent!'+
'<event-emitting-component @clicked="passClicked"></event-emitting-component>' + // <-- Please note child component
'</div>',
'methods': {
passClicked : function(){
this.$emit('clicked')
}
}
});
And then in the html template add the same:
<event-emitting-component-parent @clicked="methodOnRootInstance"></event-emitting-component-parent>
I know I can get it to work like this, however it doesn't seem very elegant. I've looked in the docs and there are functions such as sync
although I don't think it's what I need, I'm struggling to find the correct approach.
Bonus question: can vuex help with stuff like this?