This is my custom checkbox component:
<template>
<label class="checkbox">
<input
type="checkbox"
:checked="isChecked"
@change="change"
>
<span />
<slot />
</label>
</template>
<script>
export default {
name: 'Checkbox',
model: {
prop: 'selectedValues',
event: 'change'
},
props: {
value: {
type: String,
required: true
},
selectedValues: {
type: Array,
default: null
},
checked: {
type: Boolean,
default: false
}
},
computed: {
isChecked() {
return this.selectedValues.includes(this.value);
}
},
created() {
if(this.checked) {
const selectedValues = this.selectedValues;
selectedValues.push(this.value);
this.$emit('change', selectedValues);
}
},
methods: {
change() {
const selectedValues = Array.from(this.selectedValues).slice();
const found = selectedValues.indexOf(this.value);
if (found !== -1) {
selectedValues.splice(found, 1);
} else {
selectedValues.push(this.value);
}
this.$emit('change', selectedValues);
}
}
};
</script>
<style lang="scss">
label.checkbox {
position: relative;
user-select: none;
display: inline-flex;
cursor: pointer;
input {
display: none;
&:checked ~ span {
background: #EEE;
&:after {
visibility: visible;
}
}
}
span {
width: 25px;
height: 25px;
border: 1px solid #EEE;
display: inline-block;
transition: all linear 0.3s;
margin-right: 5px;
&:after {
content: "";
position: absolute;
top: 3px;
left: 9px;
border-bottom: 3px solid #FFF;
border-right: 3px solid #FFF;
height: 13px;
width: 5px;
transform: rotate(45deg);
visibility: hidden;
}
}
}
</style>
Inside my form:
<Checkbox
v-model="selectedBrands"
value="bmw"
checked
>
BMW
</Checkbox>
<Checkbox
v-model="selectedBrands"
value="audi"
checked
>
Audi
</Checkbox>
<Checkbox
v-model="selectedBrands"
value="mazda"
>
Mazda
</Checkbox>
computed: {
selectedBrands: {
get() {
return this.$store.state.selectedBrands;
},
set(value) {
this.$store.commit('setSelectedBrands', {selectedBrands: value});
}
}
}
Vuex store:
export default new Vuex.Store(
{
strict: process.env.NODE_ENV !== 'production',
state: {
selectedBrands: []
},
mutations: {
setSelectedBrands(state, payload) {
state.selectedBrands = payload.selectedBrands;
},
}
});
This actually works, but I get vuex error: Error: [vuex] do not mutate vuex store state outside mutation handlers.
However I can change the created() hook in my checkbox component like this:
created() {
if(this.checked) {
const selectedValues = Array.from(this.selectedValues).slice();
selectedValues.push(this.value);
this.$emit('change', selectedValues);
}
}
The vuex error will go away, but only the last checkbox component (with checked prop) will be checked (in this example Audi). My guess is this happens, because components are rendering asynchronically? Would be happy to hear correct explanation.
My goal is to create a custom checkbox component that supports multiple checkbox v-model array binding (using vuex!) + setting the initial checked state.
I've spent many hours trying to figure out the proper solution. Will be very thankful for your time and help! Thank you in advance!