I have looked at many examples of how to do two-way binding of model data, but examples with text inputs are reported everywhere. I work according to the same scheme and get errors.
const models = ref({
teams: {
items: usePage().props.value.teams,
selected: [],
isCheckAll: false,
},
});
<template>
<LineTeamsIndex
v-model:selected-items="models.teams.selected"
v-model:isCheckAll="models.teams.isCheckAll"
:teams="$page.props.teams"
@checkAll="checkAll"
>
</LineTeamsIndex>
</template>
child
<script setup>
defineEmits(["update:selectedItems", "update:isCheckAll", "checkAll"]);
const props = defineProps({
teams: Object,
selectedItems: Object,
isCheckAll: Boolean,
});
</script>
<template>
<template v-slot:body>
<tr v-for="team in $page.props.teams.data" :key="team.id">
<td>
<div >
<input
:id="team.id"
:value="team.id"
:checked="selectedItems.includes(team.id)"
@change="
$emit(
'update:selectedItems',
$event.target.value
)
"
type="checkbox"
/>
</div>
</td>
<td>{{ team.id }}</td>
<td>
{{ team.name }}
</td>
</tr>
</template>
</template>
Here is a part of the code related to the SelectedItems array. Two-way binding via the built-in v-model is required. But it either doesn't work, or I get a data mismatch error " [Vue warn]: Invalid prop: type check failed for prop "SelectedItems". Expected Object, got String with value "88"". Tell me how to correctly transfer (use) the built-in v-model vue 3 to add data to the array and delete using concise code? Despite the fact that in the child component I have 2 models (not one) that are bound in the parent component.
CodePudding user response:
Sounds like it's a prop data type issue. You're saying that selectedItems
should be a Javascript Object
when passing it as a prop, but you're passing String
instead.
Either change the expected data type:
defineEmits(["update:selectedItems", "update:isCheckAll", "checkAll"]);
const props = defineProps({
teams: Object,
selectedItems: String, // This is changed to 'String'
isCheckAll: Boolean,
});
or pass the value through as an object instead:
v-model:selected-items="{slectedItems: models.teams.selected}"
CodePudding user response:
When you emit $event.target.value
it's the string value of the checkbox (equal to team.id), but the v-model is an array and you can't assign a string to an array. You need to instead emit an array with all the checkbox values that the v-model should contain.
Instead of emitting from the template, call a method on @change
:
<input
:id="team.id"
:value="team.id"
:checked="selectedItems.includes(team.id)"
@change="updateSelection($event.target.value)"
type="checkbox"
/>
In the method, make a shallow copy of the prop array. Push or splice the updated checkbox value to/from the array. Emit that array with your @update:selectedItems
event. I also include one way you might update the isCheckAll
v-model
const updateSelection = checkboxVal => {
const selectedItemsCopy = [...props.selectedItems];
const index = selectedItemsCopy.indexOf(checkboxVal);
if (index !== -1) {
selectedItemsCopy.splice(index, 1);
} else {
selectedItemsCopy.push(checkboxVal);
}
emit('update:selectedItems', selectedItemsCopy);
if (selectedItemsCopy.length === props.teams.data.length) {
emit('update:isCheckAll', true);
} else {
emit('update:isCheckAll', false);
}
};