如何将v-model="item.checked"
作为if
的条件放在validations()
下面?
<table>
<tr v-for="(item, i) of $v.timesheet.items.$each.$iter" >
<div>
<td>
<input
type="checkbox"
v-model="item.checked"
v-on:click="disable(i)"
/>
</td>
<td>
<input
type="text"
:id="'total_hour-' + i"
/>
</td>
</div>
</tr>
<tr>
<div>
<td>
<button
type="button"
class="btn btn-sm btn-primary"
@click="itemCount++"
>Add Row
</button>
</td>
</div>
</tr>
</table>
<script>
import { required, minLength } from "vuelidate/lib/validators";
export default {
data() {
return {
itemCount: 1,
timesheet: { items: [{ total_hour: "", checked: false }] },
}
},
methods: {
disable(index){
const check =
document.getElementById('total_hour-' + index).disabled
$('#total_hour-' + index).attr('disabled', !check);
}
},
watch: {
itemCount(value, oldValue) {
if (value > oldValue) {
for (let i = 0; i < value - oldValue; i++) {
this.timesheet.items.push({
total_hour: "",
checked: false,
})
}
} else {
this.timesheet.items.splice(value);
}
}
},
validations() {
if ( ? ) {
return {
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { total_hour: {required} }
}
}
}
} else {
return {
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { total_hour: {} }
}
}
}
}
}
}
</script>
所以据我所知,只有当checked
为真时,您才希望total_hour
是必需的字段。Vuelidate为此提供了一个很好的内置验证器,名为requiredIf
。它是一个上下文化的验证器,所以你可以引用同级属性。
import { required, requiredIf, minLength } from 'vuelidate/lib/validators';
export default {
...
validations: {
timesheet: {
items: {
required,
minLength: minLength(1),
$each: {
total_hour: {
required: requiredIf('checked'),
},
},
},
},
},
}
我在你的代码中看到的另一个问题是,你试图迭代$v字段。$v字段用于获取字段的验证状态,您不应该设置$v字段。使用它们作为组件的v-model
将使vue设置$v字段。试试这个:
<tr v-for="(item, i) in timesheet.items">
所以,有一些事情可以改进你的代码。
用方法替换watcher
观察者很难调试并且可能导致副作用。它们应该只在真正必要的时候使用。相反,创建一个方法,它添加一行:
addRow() {
this.timesheet.items.push({
total_hour: "",
checked: false,
})
}
对于删除一行,执行相同的操作。只需创建一个方法。
为每个条目创建一个组件
通过为时间表项创建子组件,您可以更容易地处理验证,并且可以更好地对单个条目的更改做出反应。
<table>
<TimesheetItemRow
v-for="(item) of $v.timesheet.items.$each.$iter"
:item="item"
/>
<tr>
...
</tr>
</table>
为了跟踪父组件中的所有时间表项,您可能希望从子组件向父组件发出一个事件,其中包含新条目数据。
不要使用jQuery或JavaScript代码来操作DOM
和以前一样,这些东西应该只在非常非常边缘的情况下使用。像Vue.js这样的前端框架的一个好处是,你不需要这样做。
现在,每个条目都有一个组件,很容易在模板
中直接禁用输入这是时间表项目组件的一些(未经测试的)代码:
<template>
<tr>
<td>
<input
type="checkbox"
value="item.checked
@click="onClickCheckbox"
/>
</td>
<td>
<input
type="text"
@input="onUpdateTotalHour"
:disabled="!item.checked
/>
</td>
</tr>
</template>
<script>
import { required } from "vuelidate/lib/validators";
export default {
props: {
item: {
type: Object
}
},
methods: {
onClickCheckbox (value) {
this.$emit('on-click-checkbox', value)
},
onUpdateTotalHour (value) {
this.$emit('on-update-total-hour', value)
}
},
validations () {
if (this.item.checked) {
return {
item: {
total_hour: { required }
}
}
}
return {
item: {
total_hour: {}
}
}
}
}
</script>
父组件需要跟踪所有的项,并且需要对发出的事件做出反应。