How do you emit event inside recursive child components vuejs
Taking the tree example from vue site https://v2.vuejs.org/v2/examples/tree-view.html
How would you transmit on click to the parent each clicked elements id?
In the case of recursive elements, you can create an event bus in the parent, pass it to the children as a prop, and have each prop pass it to any children they generate.
Each child emits events on the bus, and the parent handles them. I copied the tree-view exercise you linked and added the bus functionality.
// demo data
var data = {
name: 'My Tree',
children: [{
name: 'hello'
},
{
name: 'wat'
},
{
name: 'child folder',
children: [{
name: 'child folder',
children: [{
name: 'hello'
},
{
name: 'wat'
}
]
},
{
name: 'hello'
},
{
name: 'wat'
},
{
name: 'child folder',
children: [{
name: 'hello'
},
{
name: 'wat'
}
]
}
]
}
]
};
var itemId = 0;
// define the item component
Vue.component('item', {
template: '#item-template',
props: {
model: Object,
bus: Object
},
data: function() {
return {
open: false,
id: ++itemId
}
},
computed: {
isFolder: function() {
return this.model.children &&
this.model.children.length
}
},
methods: {
toggle: function() {
if (this.isFolder) {
this.open = !this.open;
this.bus.$emit('toggled', this.id);
}
},
changeType: function() {
if (!this.isFolder) {
Vue.set(this.model, 'children', [])
this.addChild()
this.open = true
}
},
addChild: function() {
this.model.children.push({
name: 'new stuff'
})
}
}
})
// boot up the demo
var demo = new Vue({
el: '#demo',
data: {
treeData: data,
bus: new Vue()
},
created() {
this.bus.$on('toggled', (who) => {
console.log("Toggled", who);
});
}
})
body {
font-family: Menlo, Consolas, monospace;
color: #444;
}
.item {
cursor: pointer;
}
.bold {
font-weight: bold;
}
ul {
padding-left: 1em;
line-height: 1.5em;
list-style-type: dot;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<!-- item template -->
<script type="text/x-template" id="item-template">
<li>
<div :class="{bold: isFolder}" @click="toggle" @dblclick="changeType">
{{model.name}}
<span v-if="isFolder">[{{open ? '-' : '+'}}]</span>
</div>
<ul v-show="open" v-if="isFolder">
<item class="item" :bus="bus" v-for="model in model.children" :model="model">
</item>
<li class="add" @click="addChild">+</li>
</ul>
</li>
</script>
<p>(You can double click on an item to turn it into a folder.)</p>
<!-- the demo root element -->
<ul id="demo">
<item class="item" :bus="bus" :model="treeData">
</item>
</ul>