[英]How to sync checkboxes between Vue 3 parent and child components
I have a Vue 3 InertiaJS app that contains a parent/child set of components where the parent component contains a form, along with a child component that searches for users and displays the results in a table where each row has a checkbox, so I can select users and then submit them as part of the form.我有一个 Vue 3 InertiaJS 应用程序,其中包含一组父/子组件,其中父组件包含一个表单,以及一个子组件,用于搜索用户并将结果显示在每行都有一个复选框的表中,因此我可以select 用户,然后将它们作为表单的一部分提交。 What I need to do is sync the parent component with the checkbox values from the child component.
我需要做的是将父组件与子组件的复选框值同步。 Here is what I have.
这是我所拥有的。
Create.vue
<script setup>
import {Inertia} from '@inertiajs/inertia';
import {ref} from 'vue';
import {Head, Link, useForm} from '@inertiajs/inertia-vue3'
const form = useForm({
name: '',
checkedNames: []
});
const checkedNames = ref([])
const props = defineProps({
users: Object
})
</script>
<template>
<area-user-select
:users="props.users"
@searchUsers="searchUsers"
v-model:checkedNames="checkedNames"
></area-user-select>
</template>
AreaUserSelect.vue
(child component) AreaUserSelect.vue
(子组件)
<script setup>
import { Head } from '@inertiajs/inertia-vue3';
import Icon from '@/Components/Icon.vue';
import {ref} from 'vue';
const props = defineProps({
users: Object,
filters: Object,
checkedNames: Array
})
</script>
<template>
<div>
...
<div v-if="users.data.length > 0">
<table class="table-auto">
<thead>
<tr class="text-left font-bold">
<th class="pb-4 pt-6 px-6 text-sm">Select</th>
<th class="pb-4 pt-6 px-6 text-sm">Name</th>
<th class="pb-4 pt-6 px-6 text-sm">Last Name</th>
<th class="pb-4 pt-6 px-6 text-sm">Member Number</th>
<th class="pb-4 pt-6 px-6 text-sm">Status</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users.data" :key="user.id" class="hover:bg-gray-100 focus-within:bg-gray-100">
<td class="border-t">
<input
type="checkbox"
name="selected"
:value="user.id"
@input="$emit('update:checkedNames', $event.target.value)"
/>
</td>
<td class="border-t">
{{ user.first_name }}
</td>
<td class="border-t">
{{ user.last_name }}
</td>
<td class="border-t">
{{ user.member_number }}
</td>
<td class="border-t">
{{ user.status }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
This works, sort of.这行得通,有点。 In my parent component, if I display the value of
checkedName
it only contains the value of the last item checked, not an array of all selected values.在我的父组件中,如果我显示
checkedName
的值,它只包含最后检查的项目的值,而不是所有选定值的数组。
What do I need to change so that all selected items are synced back to the parent ( Create.vue
) component?我需要更改什么才能将所有选定项目同步回父 (
Create.vue
) 组件?
You can do it this way:你可以这样做:
Bind your parent to your component with 'v-model':使用“v-model”将您的父级绑定到您的组件:
<my-component ... v-model="checkedNames"/>
Docs: Component v-model文档: 组件 v-model
Bind your checkboxes to a internal component property:将您的复选框绑定到内部组件属性:
<input type="checkbox" ... v-model="checked" />
Docs: Form Input Bindings - Checkbox文档:表单输入绑定 - 复选框
End send updates with watch
to the parent:结束向父级发送带有
watch
的更新:
watch(checked, (newVal) => { emit('update:modelValue', newVal) });
Here is the playground:这是游乐场:
const { createApp, ref, watch } = Vue; const users = [ { id: 1, name: "User 1" }, { id: 2, name: "User 2" } ]; const myComponent = { props: ['items'], emits: ['update:modelValue'], setup(props, { emit }) { const checked = ref([]); watch(checked, (newVal) => { emit('update:modelValue', newVal) }); return {emit, checked} }, template: '#my-checkbox' } const App = { components: { myComponent }, setup() { const checkedNames = ref([]); const setCheckedNames = (newVal) => checkedNames.value = newVal; return { users, checkedNames, setCheckedNames } } } const app = createApp(App) app.mount('#app')
<div id="app"> Checked: {{checkedNames}}<br /><br /> <my-component:items="users" v-model="checkedNames"/> </div> <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script> <script type="text/x-template" id="my-checkbox"> <div v-for="user in items"> <input type="checkbox" name="selected":value="user.id" v-model="checked" /> <label>{{user.name}}</label> </div> </script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.