Vue3.x
需求:添加/编辑题目页面,支持添加/编辑多条,点击提交按钮,做表单校验,此时的表单是包含多个题目,需要对所有的题目做校验,做法如下:
表单里有循环项 UpdateFormNode
<template>
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" label-position="left">
<div class="content" id="content">
<template v-for="(node, index) in formData.list" :key="node">
<div class="content-node">
<UpdateFormNode :index="index" :total="formData.list" :node-data="node" :form-rules="formRules" @formChange="formChange"/>
<div class="content-node__delete" v-if="formData.list.length > 1">
<el-button type="text" @click="remove(index)">删除</el-button>
</div>
</div>
</template>
</div>
</el-form>
</template>
循环项 UpdateFormNode
<template>
<div>
<el-form-item label="参考答案" :prop="'optionList.'+index+'.solution'" :rules="formRules.solution">
<el-input v-model="item.solution" type="textarea" :maxlength="500" show-word-limit :rows="6" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="分值" :prop="'optionList.'+index+'.score'" :rules="formRules.score">
<el-input v-model="item.score" placeholder="请输入分值" />
</el-form-item>
</div>
</template>
循环表单项的校验, 注意prop的写法 :prop="'optionList.'+index+'.solution'"
,这样校验时取值 model.optionList.0.solution,根据指明的 rules :rules="formRules.solution"
进行校验。
Vue2.x
原来
之前处理循环输入框的校验是通过循环生成一个 form 表单,比较复杂 后面想想,这样处理太繁琐了,不仅要循环生活 form ,而且校验的时候也是循环校验的。
<template v-for="(item, index) in form.optionList" :key="index">
<el-form :ref="`formRef${index}`" :model="item" :rules="formRules">
<el-form-item label="分值" prop="score">
<el-input v-model="item.score" />
</el-form-item>
</el-form>
</template>
改进
props: {
...,
prop: String,
rules: [Object, Array],
...,
}
- 循环列表下的校验,指定列表项下的校验项, 指定其 prop 和 rule;
- 其中 prop 是 从model 开始取值的, 所以只需要指定 model 后面的路径即可;
- 列表项下的校验项的 prop,是从model开始取值的,所以只需要从 model 指定值的子级开始定位即可,并且要注意定位方式
- 要注意定位方式,
:prop="'optionList['+index+'].solution'"
或:prop="'optionList.'+index+'.solution'"
- 通过 rule 指定该项的校验规则
<template>
<el-form ref="formRef" :model="form" :rules="formRules" label-width="80px" label-position="left">
<div v-for="(item, index) in form.optionList" :key="index">
<!-- 这里这样也行 :prop="'optionList['+index+'].solution'" -->
<el-form-item label="参考答案" :prop="'optionList.'+index+'.solution'" :rules="formRules.solution">
<el-input v-model="item.solution" type="textarea" :maxlength="500" show-word-limit :rows="6" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="分值" :prop="'optionList.'+index+'.score'" :rules="formRules.score">
<el-input v-model="item.score" placeholder="请输入分值" />
</el-form-item>
</div>
</el-form>
</template>
<script>
import { checkNumberByDot, } from "./check";
const checkStore = (rule, value, callback) => {
console.log("checkStore", value);
if(!value || !checkNumberByDot.test(value)) {
return callback(new Error("请输入至多一位小数的数"));
}
callback();
}
export default {
data() {
return {
form: {
optionList: [
{ id: 1,solution: "",score: "", },
{ id: 2, solution: "", score: "",},
]
},
}
},
computed: {
formRules() {
return {
solution: [{required: true, message: "请选择/输入内容",}],
score: [{required: true, validator: checkStore,}],
};
},
}
}
</script>