Reputation: 4885
I have got a simple dropdown component, which simply allows me to hide and display some HTML, it's very basic.
However if I use this same component within itself, clicking the Test 2
dropdown toggle will collapse the first dropdown...
<dropdown>
<li slot-scope="{ display, toggleDisplay }" @click="toggleDisplay()" :class="{ active: display }">
Test
<ul>
<dropdown>
<li slot-scope="{ display, toggleDisplay }" @click="toggleDisplay()" :class="{ active: display }">
Test 2
</li>
</dropdown>
</ul>
</li>
</dropdown>
Why is this? Also, I should be able to just do display = !display
within the click event to toggle it rather than a function?
The component:
<script>
export default {
props: [ 'expanded' ],
data: function() {
return {
display: !!(this.expanded)
}
},
render() {
return this.$scopedSlots.default({
display: this.display,
toggleDisplay: this.toggleDisplay
})
},
methods: {
toggleDisplay() {
this.display = !this.display;
}
}
}
</script>
Upvotes: 3
Views: 56
Reputation: 3536
This is called event bubbling
(https://javascript.info/bubbling-and-capturing) and to prevent it use stopPropagation();
.
I've removed the brackets (@click="toggleDisplay"
) to set $event
automatically. You can also write: @click="toggleDisplay($event)"
.
Vue.component("dropdown", {
props: ["expanded"],
data: function() {
return {
display: !!this.expanded
};
},
render() {
return this.$scopedSlots.default({
display: this.display,
toggleDisplay: this.toggleDisplay
});
},
methods: {
toggleDisplay(e) {
e.stopPropagation(); // this line
this.display = !this.display;
}
}
});
new Vue().$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.10/vue.js"></script>
<div id="app">
<dropdown>
<li slot-scope="{ display, toggleDisplay }" @click="toggleDisplay" :class="{ active: display }">
{{ display }}
Test
<ul>
<dropdown>
<li slot-scope="{ display, toggleDisplay }" @click="toggleDisplay" :class="{ active: display }">
{{ display }}
Test 2
</li>
</dropdown>
</ul>
</li>
</dropdown>
</div>
Upvotes: 2