Element循环表单校验

1,141 阅读1分钟

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],
    ...,
}

image.png

  • 循环列表下的校验,指定列表项下的校验项, 指定其 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>