I have some products that I want to filter based on their category using checkboxes.
To do so, I have a parent component which passes the possible categories (e.g. A, B and C) to the child and keeps track of the checked/selected categories:
Parent.vue
<template>
<FilterCheckboxItem
ref="Category"
name="Category"
:FilterOptions="CategoryOptions"
v-model="FilteredCategories"
/>
</template>
<script>
export default {
data(){
return {
FilteredCategories: [],
CategoryOptions: ["A","B","C"]
}
}
</script>
And the child component looks like this (simplified):
FilterCheckboxItem.vue
<template>
<div
v-for="FilterOption in FilterOptions"
>
<input
type="checkbox"
:value="FilterOption"
v-model="checked"
/>
</div>
</template>
<script>
export default {
props: {
FilterOptions: {
type: Array,
},
modelValue: {
type: Array,
},
},
emits: ['update:modelValue'],
setup(props, { emit }) {
const checked = ref([]);
watch(checked, (newVal) => {
emit('update:modelValue', newVal);
});
return { emit, checked };
},
</script>
This works as intended.
However, when I would like to add the same child component again (for example 1 filterbutton in the normal menu and 1 in the mobile-menu) the arrays from the 2 childs are not aligned anymore. For example, I select Category "A" on the first child component, then the second child component is not updated properly (Category "A") will not be checked.
How can I make sure that the whenever I change something in the first child-component it updates the parent component but also makes sure that the second child-component is updated properly?
I would expect this to work since they are referred to the same v-model property.
The v-model in the parent, which exists in the Child component as modelValue
, is not the same v-model used on the actual inputs which is checked
. When checked
update you use a watcher to update the parent v-model. There's no equivalent code to update checked
when the v-model updates, but there doesn't need to be. Just use modelValue
as your v-model on the input. No need to have checked
or a watcher at all.
FilterCheckboxItem.vue
<template>
<div
v-for="(FilterOption, index) in FilterOptions"
>
<label for="lname">{{FilterOption}}</label>
<input
type="checkbox"
:value="FilterOption"
v-model="modelValue[index]"
/>
</div>
</template>
<script>
export default {
props: {
FilterOptions: {
type: Array,
},
modelValue: {
type: Array,
},
},
}
</script>