Vue v-model 不适用于数组的单个索引
Vue v-model does not work with individual index of array
我有一行输入:一个复选框和一个下拉按钮。
然后,还有另一个按钮可以添加新的输入行。
复选框在选中时会禁用下拉菜单并使其成为非必需项。
<template>
<div>
<tr v-for="(item, i) of timesheet.items" :key="i">
<div>
<td>
<input
type= "checkbox"
v-model="checked"
id= "{{ 'disable' + i }}"
v-on:click= "disable(i)"
>
</td>
<td>
<select2
:id="'project_id-' + i"
v-bind:class="{
'is-invalid': item.project_id.$error,
'is-valid':
item.project_id.$dirty &&
!item.project_id.$error,
}"
>
<option value="">Select</option>
<option v-for="(project) in projects"
:selected="project.id == timesheet.project_id"
:key="project.id"
:value="project.id">{{ project.name }}</option>
</select2>
</td>
<td>
<button
type="button"
class="btn btn-sm btn-primary"
@click="itemCount++"
>Add Row
</button>
</td>
</div>
</tr>
</div>
</template>
<script>
import { required, minLength } from "vuelidate/lib/validators";
export default {
data() {
return {
checked: false,
timesheet: { items: [{ project_id: "" }] },
}
},
validations() {
if (!this.checked) {
return{
itemCount: 1,
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { project_id: { required }}
}
}
}
}else{
return{
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { project_id: {} }
}
}
}
}
},
watch: {
itemCount(value, oldValue) {
if (value > oldValue) {
for (let i = 0; i < value - oldValue; i++) {
this.timesheet.items.push({
project_id: "",
checked: false,
})
}
} else {
this.timesheet.items.splice(value);
}
}
},
methods: {
disable(index){
const check =
document.getElementById('project_id-' + index).disabled
$('#project_id-' + index).attr('disabled', !check);
}
},
}
</script>
第一个复选框按预期工作,但是每当添加另一行时,总是预先选中新的复选框,其行为与第一个复选框完全相反。
那么,我的问题是如何修复我的 v 模型?
我发现您的代码存在一些问题。
首先,checkbox有id= "{{ 'disable' + i }}"
,不允许在属性中使用插值,应该使用:id="'disable' + i"
.
其次,我仍然不明白你在哪里定义了 itemsCount
,我假设它在 data
.
下
第三,您对所有复选框使用相同的 v 模型,这是 data
下的 checked
模型。因此,单击任何复选框都会更改 checked
,并且此更改也会在其他复选框中更新。这就是为什么您的所有复选框都同步运行的原因。
第四,你定义了timesheet: { items: [{ project_id: "" }] }
,所以item
只包含project_id
属性。但稍后当您添加项目时,您使用 this.timesheet.items.push({ project_id: "", checked: false })
,这告诉我您正在尝试为每个 item
使用 checked
属性,您打算将其用于每个复选框.嗯,那你的想法是对的。
您需要做的是在 data
中向 items
添加一个 checked
属性,并将其用作复选框的 v-model。
data() {
return {
itemCount: 1,
timesheet: { items: [{ project_id: "", checked: false }] },
};
},
<input
type="checkbox"
v-model="item.checked"
:id="'disable' + i"
v-on:click="disable(i)"
/>
我有一行输入:一个复选框和一个下拉按钮。
然后,还有另一个按钮可以添加新的输入行。
复选框在选中时会禁用下拉菜单并使其成为非必需项。
<template>
<div>
<tr v-for="(item, i) of timesheet.items" :key="i">
<div>
<td>
<input
type= "checkbox"
v-model="checked"
id= "{{ 'disable' + i }}"
v-on:click= "disable(i)"
>
</td>
<td>
<select2
:id="'project_id-' + i"
v-bind:class="{
'is-invalid': item.project_id.$error,
'is-valid':
item.project_id.$dirty &&
!item.project_id.$error,
}"
>
<option value="">Select</option>
<option v-for="(project) in projects"
:selected="project.id == timesheet.project_id"
:key="project.id"
:value="project.id">{{ project.name }}</option>
</select2>
</td>
<td>
<button
type="button"
class="btn btn-sm btn-primary"
@click="itemCount++"
>Add Row
</button>
</td>
</div>
</tr>
</div>
</template>
<script>
import { required, minLength } from "vuelidate/lib/validators";
export default {
data() {
return {
checked: false,
timesheet: { items: [{ project_id: "" }] },
}
},
validations() {
if (!this.checked) {
return{
itemCount: 1,
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { project_id: { required }}
}
}
}
}else{
return{
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { project_id: {} }
}
}
}
}
},
watch: {
itemCount(value, oldValue) {
if (value > oldValue) {
for (let i = 0; i < value - oldValue; i++) {
this.timesheet.items.push({
project_id: "",
checked: false,
})
}
} else {
this.timesheet.items.splice(value);
}
}
},
methods: {
disable(index){
const check =
document.getElementById('project_id-' + index).disabled
$('#project_id-' + index).attr('disabled', !check);
}
},
}
</script>
第一个复选框按预期工作,但是每当添加另一行时,总是预先选中新的复选框,其行为与第一个复选框完全相反。
那么,我的问题是如何修复我的 v 模型?
我发现您的代码存在一些问题。
首先,checkbox有id= "{{ 'disable' + i }}"
,不允许在属性中使用插值,应该使用:id="'disable' + i"
.
其次,我仍然不明白你在哪里定义了 itemsCount
,我假设它在 data
.
第三,您对所有复选框使用相同的 v 模型,这是 data
下的 checked
模型。因此,单击任何复选框都会更改 checked
,并且此更改也会在其他复选框中更新。这就是为什么您的所有复选框都同步运行的原因。
第四,你定义了timesheet: { items: [{ project_id: "" }] }
,所以item
只包含project_id
属性。但稍后当您添加项目时,您使用 this.timesheet.items.push({ project_id: "", checked: false })
,这告诉我您正在尝试为每个 item
使用 checked
属性,您打算将其用于每个复选框.嗯,那你的想法是对的。
您需要做的是在 data
中向 items
添加一个 checked
属性,并将其用作复选框的 v-model。
data() {
return {
itemCount: 1,
timesheet: { items: [{ project_id: "", checked: false }] },
};
},
<input
type="checkbox"
v-model="item.checked"
:id="'disable' + i"
v-on:click="disable(i)"
/>