I've been trying to create a simple component with a styled checkbox and corresponding label. The values (strings) of all selected checkboxes should be stored in an array. This works for plain html checkboxes:
<template> <div> <div class="mt-6"> <div> <input type="checkbox" value="EVO" v-model="status" /> <label for="EVO">EVO</label> </div> <div> <input type="checkbox" value="Solist" v-model="status" /> <label for="Solist">Solist</label> </div> <div> <input type="checkbox" value="SPL" v-model="status" /> <label for="SPL">SPL</label> </div> </div> <div class="mt-3">{{status}}</div> </div> </template> <script setup> import { ref } from 'vue' let status = ref([]); </script>
It results in the following desired situation:
Now, if I replace these checkboxes with a custom checkbox component, I can't get it to work. If I check a box, the value it emits seems to replace the status
array instead of being added to or removed from it, resulting in the following:
So for some reason all the checkboxes are checked by default and when I click on one of them they all get unchecked and the status
value goes to false
, clicking any checkbox again will select all checkboxes and make status
true
.
Now, I know that returning whether the box is checked in the emission returns a true or false value, but I don't understand how Vue does this with native checkboxes and how to achieve this behavior with my component. p>
This is the code for my checkbox component:
<template> <div class="mt-1 relative"> <input type="checkbox" :id="id ?? null" :name="name" :value="value" :checked="modelValue ?? false" class="bg-gray-200 text-gold-500 rounded border-0 w-5 h-5 mr-2 focus:ring-2 focus:ring-gold-500" @input="updateValue" /> {{ label }} </div> </template> <script setup> const props = defineProps({ id: String, label: String, name: String, value: String, errors: Object, modelValue: Boolean, }) const emit = defineEmits(['update:modelValue']) const updateValue = function(event) { emit('update:modelValue', event.target.checked) } </script>
And the parent component just uses a different template:
<template> <div> <div class="mt-6"> <Checkbox v-model="status" value="EVO" label="EVO" name="status" /> <Checkbox v-model="status" value="Solist" label="Solist" name="status" /> <Checkbox v-model="status" value="SPL" label="SPL" name="status" /> </div> <div class="mt-3">{{status}}</div> </div> </template>
I tried to look at this answer by StevenSiebert but it uses an object and I want to replicate the original Vue behavior using native checkboxes.
I also referred to the official Vue documentation at v-model
but don't understand why this works differently for native checkboxes than for components.
The v-model for each checkbox is the same and may resemble the following code snippet: