My component is functioning perfectly except for the issue of binding a string instead of an array. The events are firing correctly.
In the multi-select version, when I select and deselect items, the multiSelected
variable is updated properly. However, when selecting another value within the single select, the singleSelected
variable remains unchanged even though the same event is triggered.
I have simplified the code below so you can easily see the logic and problem:
Vue.component('dropdown', {
template: `<div class="dropdown">
<label v-for="item in items" :key="item.value" :class="{selected:selected.indexOf(item.value) > -1}">
{{ item.label }}
<input type="checkbox" :value="item.value" :checked="selected.indexOf(item.value) > -1" @change="selected = $event" />
</label>
</div>`,
props: [ 'value', 'items', 'multiSelect' ],
computed: {
selected: {
get: function() {
if (this.value === undefined) {
return [];
}
if (!Array.isArray(this.value)) {
return [ this.value ];
}
return this.value;
},
set: function($event) {
let current = this.selected;
if (!this.multiSelect) {
current = $event.target.value;
}
if (this.multiSelect && !$event.target.checked) {
const index = current.indexOf($event.target.value);
if (index > -1) {
current.splice(index, 1)
}
}
if (this.multiSelect && $event.target.checked) {
current.push($event.target.value);
}
console.log(current);
this.$emit('value', current);
}
}
}
});
Vue.component('wrapper', {
template: `
<div>
Single
<dropdown :items="items" v-model="singleSelected" :multi-select="false" name="single" />
<br />
Multi
<dropdown :items="items" v-model="multiSelected" :multi-select="true" name="multi" />
<p>Models</p>
<p>singleSelected: {{ singleSelected }}</p>
<p>multiSelected: {{ multiSelected }}</p>
</div>
`,
data() {
return {
items: [{value:'bmw',label:'BMW',count:1},{value:'audi',label:'Audi',count:1},{value:'kia',label:'KIA',count:1}],
multiSelected: ['kia'],
singleSelected: 'kia',
}
}
});
new Vue().$mount('#app');
.dropdown {
border: 1px solid black;
padding: 10px;
display: block;
}
label {
margin: 5px;
}
.selected {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<wrapper>
</wrapper>
</div>