Reputation: 25
I'm new to vue (less than a week) and I'm rewriting a hobby project to get up and going. Decided to try out components and ran into and issue. One of my sub-components emits just fine, but the other one is not received by the parent. The vue-devtools chrome extension tells me that sidenavselect is indeed emitting the close event, but the sidenav v-on:close is not being triggered.
<sidenav v-on:close="sidebar_show = false" v-show="sidebar_show">
<sidenavbutton @click="draw_board">Start Round</sidenavbutton>
<sidenavselect v-model="location" :datafield="locations" title="Location"></sidenavselect>
</sidenav>
Vue.component('sidenav', {
props: ['method'],
template: `
<div class="sidenav" v-on:close="handle_close" @click.self="handle_close">
<div class="contents" v-on:close="handle_close">
<span class="closebtn" v-on:click="handle_close">×</span>
<slot></slot>
</div>
</div>
`,
methods: {
handle_close: function() {
this.$emit('close');
}
}
});
Vue.component('sidenavbutton', {
template: `
<button tabindex="-1" @click="handle_click"><slot></slot></button>
`,
methods: {
handle_click: function() {
this.$emit('click');
this.$emit('close');
}
}
});
Vue.component('sidenavselect', {
props: ['datafield', 'title', 'value'],
template: `
<div class="sidenav-box">
{{title}}<br>
<select tabindex="-1" v-bind:value="value" @input="handle_close">
<option v-for="this_data in datafield" :value="this_data.value">{{this_data.label}}</option>
</select>
</div>
`,
methods: {
handle_close: function(event) {
this.$emit('input', event.target.value);
this.$emit('close');
}
}
});
Upvotes: 1
Views: 379
Reputation: 25
The answer to my issue was that the methods attached to the buttons were still closing the sidenav from before I was working with components.
User skirtle was correct in that each component I used needed to have @close on them.
Upvotes: 0
Reputation: 1991
Vue.component("sidenav", {
template: `
<div class="sidenav" @close="handle_close" @click.self="handle_close">
<div class="contents" @close="handle_close">
<span class="closebtn" @click="handle_close">×</span>
<slot></slot>
</div>
</div>
`,
methods: {
handle_close: function() {
this.$emit("close");
}
}
});
Vue.component("sidenavbutton", {
template: `
<button @click="handle_click"><slot></slot></button>
`,
methods: {
handle_click: function() {
this.$emit("click");
this.$emit("close");
}
}
});
Vue.component("sidenavselect", {
props: ["value"],
template: `
<div class="sidenav-box">
<select :value="value" @input="handle_close">
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
</div>
`,
methods: {
handle_close: function(event) {
this.$emit("input", event.target.value);
this.$emit("close");
}
}
});
new Vue({
data() {
return {
sidebar_show: true,
location: 0
};
},
methods: {
handle_close: function(event) {
this.sidebar_show = false;
}
}
}).$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<sidenav @close="handle_close" v-show="sidebar_show">
<sidenavbutton @close="handle_close">Start Round</sidenavbutton>
<sidenavselect @close="handle_close" v-model="location"></sidenavselect>
</sidenav>
</div>
You want to do too much at once. Take smaller steps. It's easier to catch mistakes.
Upvotes: 1