Home > Net >  vue 3 script setup bind v-model to child custom component multiple checkbox
vue 3 script setup bind v-model to child custom component multiple checkbox

Time:09-17

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);
  }
};
  • Related