element动态添加表单并验证(element-ui动态表单和验证)
导读:在使用element-ui开发中,经常会用到对动态创建的表单进行字段验证,比如新增多个类似卡片的表单,里面的字段需要做验证,此时就要使用到动态表单验证,官方文档写的有示例,但是不够清晰。除了官方示例,还可以使用循环生成多个form实现该需求。...
在使用element-ui开发中 ,经常会用到对动态创建的表单进行字段验证 ,比如新增多个类似卡片的表单 ,里面的字段需要做验证 ,此时就要使用到动态表单验证 ,官方文档写的有示例 ,但是不够清晰 。除了官方示例 ,还可以使用循环生成多个form实现该需求 。
第一种官方示例:一个Form多项
下面以实际项目中的代码为例:
<el-form ref="form" :model="form" :rules="rules" label-width="110px" size="small" style="width: 90%;"> <div v-for="(item, index) in form.list" :key="item.id" class="box-card"> <el-form-item :prop=" list. + index + .maintUnit" :rules="rules.maintUnit" label="运维单位"> <SearchOpsDepartment :value.sync="item.maintUnit"></SearchOpsDepartment> </el-form-item> <el-form-item :prop=" list. + index + .userId" :rules="rules.userId" label="运维人员"> <SearchUsers :value.sync="item.userId"></SearchUsers> </el-form-item> <div> <el-button type="text" @click="handleAdd">添加</el-button> <el-button v-if="index !== 0" type="text" @click="handleDelete(index)">删除</el-button> </div> </div> </el-form> <script> data() { return { form: { list: [{ id: Date.now() }] // 这里添加了一个当前时间戳作为循环使用的key ,如果使用index作为key ,虽然避免的报错 ,但是对性能没有什么帮助 ,而且可能增加新能问题 。 }, rules: { maintUnit: [ { required: true, message: 运维单位不能为空!, trigger: [change, blur] } ], userId: [ { required: true, message: 运维人员不能为空!, trigger: [change, blur] } ] } } } </script>注意重点
form表单里的 :model="form" :rules="rules"model和rules不能省略 ,而且这个model必须是个对象,虽然在当前例子里 ,我们的数据form其实就是一个数组 ,但是还要包裹一层成对象 。 每一项绑定prop时,一定要按照:prop=" list. + index + .maintUnit"这种格式 ,list是需要循环的数组key名 ,一定不要写成form.list ,也不是循环出的每一项item ,index是每项的下标 ,maintUnit是当前字段key值 。 每一项必须单独绑定验证规则 ,如例子中的:rules="rules.maintUnit" prop和当前字段的key值要保持一致 ,无论是动态表单还是静态表单都要保持一致 验证规则不能用正则 表单验验证时 ,一定要有默认值 。比如form里的input绑定的是v-model="form.value" ,data里定义form时一定要要加value ,如form: { value: }第二种:多个form
<CardBox v-for="(item, index) in list" :key="index" :title="item.itemName"> <el-form ref="form" :model="item" class="size-auto width-100" :rules="rules" :inline="true" size="medium" label-width="120px"> <el-form-item label="计划工程量" prop="workAmount"> <el-input v-model.trim="item.workAmount" maxlength="15" clearable placeholder="支持小数点后2位" @change="handleComputed(item, index)" /> </el-form-item> <el-form-item label="单价" prop="unitPrice"> <el-input v-model.trim="item.unitPrice" maxlength="50" show-word-limit clearable placeholder="请输入" @change="handleComputed(item, index)" /> </el-form-item> <el-form-item label="计划完成金额" prop="prepareCompletionMoney" :rules="moneyRules(item.budgetContent.budgetMoney)"> <el-input v-model.trim="item.prepareCompletionMoney" disabled maxlength="15" clearable placeholder="支持小数点后2位"> <i slot="suffix" class="el-input__icon input-unit">元</i> </el-input> </el-form-item> <el-form-item label="工作内容及标准"> <el-input v-model.trim="item.content" type="textarea" maxlength="200" show-word-limit clearable placeholder="请输入" /> </el-form-item> <el-form-item label="备注"> <el-input v-model.trim="item.remark" type="textarea" maxlength="200" show-word-limit clearable placeholder="请输入" /> </el-form-item> </el-form> </CardBox> <script> data() { return { list: [], rules: { workAmount: [{ validator: this.validNum, trigger: blur }], unitPrice: [{ validator: this.validNum, trigger: blur }], adjustmentFactor: [{ validator: this.validNum, trigger: blur }] } } }, methods: { validNum(rule, value, callback) { if (value && !isNumber2(value)) { callback(new Error(填写格式错误)) } else { callback() } }, moneyRules(budgetMoney) { return [{ validator: (rule, value, callback) => this.validMoney(rule, value, callback, budgetMoney), trigger: change }] }, validMoney(rule, value, callback, budgetMoney) { if (value) { if (value > budgetMoney) { callback(new Error(不能大于预算金额)) } else { callback() } } else { callback() } }, // 获取多个form验证结果 handleValidate() { const list = [] const validas = [] this.$refs[form].forEach((item, index) => { list.push(new Promise(resolve => { item.validate(valida => { validas.push(valida) resolve() }) }) ) }) Promise.all([...list]).then(() => { const res = !validas.some(item => item === false) return res }).catch(() => { return false }) } } </script>复杂表单的验证
很多时候会遇到其中一个值 ,需要当前项的某个值做验证 ,如上第二种表单中,要求计划完成金额不能大于预算量 ,这里有两种实现方式
1 、通过 rule.field获取到当前项下标 ,只适用第一种动态表单;
validEverydayBudgetAmount(rule, value, callback) { if (value) { if (!isNumber2(value)) { callback(new Error(填写格式错误)) return } // rule.field转为数组后第二个就是下标 const index = rule.field.split(.)[1] const budgetAmount = this.everydayCost[index].budgetAmount if (value > budgetAmount) { callback(new Error(`不能大于总预算量${budgetAmount}`)) } else { callback() } } else { callback() } },2 、把验证规则写在item行内,这样就可以通过传参获取当前项值;
<el-form-item label="计划完成金额" prop="prepareCompletionMoney" :rules="moneyRules(item.budgetContent.budgetMoney)"> // 验证规则见第二种表单的示例代码获取验证结果
第二种多个form的 ,验证结果获取较为麻烦 ,因为每个验证都是异步 ,这里使用promise方式获取 。父组件获取验证结果时 ,调用子组件内handleValidate方法 ,通过then或者await获取结果即可 。
// 获取多个form验证结果 ,具体参考第二种form代码 handleValidate() { const list = [] const validas = [] this.$refs[form].forEach((item, index) => { // 把单个验证结果处理为promise函数 ,然后添加到list中 list.push(new Promise(resolve => { item.validate(valida => { validas.push(valida) resolve() }) }) ) }) // 通过Promise.all等待几个验证都完成再处理 return Promise.all([...list]).then(() => { const res = !validas.some(item => item === false) return res }).catch(() => { return false }) }创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!