Vue+Element动态生成新表单并添加验证

我们有这样的需求,表单中默认有一条信息,用户可以再添加新的属性信息,这时候我们就需要用到动态表单,然后还添加动态验证规则。
访问在线 demo
在这里插入图片描述
点击新增属性就加一条数据
在这里插入图片描述

图片

贴html的代码

  <el-form :model="formData3" :inline="true" ref="formData3" label-width="65px" size="medium">
          <el-row v-for="(item,index) in formData3.powerAttrList" :key="index">
            <el-form-item label="参数名"
                          :prop="'powerAttrList.' + index + '.fieldDesc'"
                          :rules="[{ required: true, message: '参数名不能为空',trigger: 'change'},{max: 32, message: '不超过32个字符', trigger: 'change'}]">
              <el-input v-model="item.fieldDesc" placeholder="请输入参数名"/>
            </el-form-item>
            <el-form-item label="描述"
                          :prop="'powerAttrList.' + index + '.fieldName'"
                          :rules="[{ required: true, message: '描述不能为空',trigger: 'change'},{max: 32, message: '不超过32个字符', trigger: 'change'}]">
              <el-input v-model="item.fieldName" placeholder="请输入描述"/>
            </el-form-item>
            <el-form-item label="排序"
                          :prop="'powerAttrList.' + index + '.fieldSort'"
                          :rules="moreRules.fieldSort">
              <el-input type="number" v-model="item.fieldSort" autocomplete="off" placeholder="请输入排序"/>
            </el-form-item>
            <el-button type="danger" v-if="formData3.powerAttrList.length > 1" size="medium" @click="removeRow(index)">
              删除
            </el-button>
          </el-row>
          <el-row>
            <el-button type="primary" size="medium" @click="addRow">新增属性</el-button>
          </el-row>
        </el-form>

和普通表单验证不同的是,动态表单要新增自己的验证规则,和添加普通表单的方式一样

 formData3: {
   powerAttrList: [{
     fieldName: '',
     fieldSort: '',
     fieldDesc: '',
   }],
 },
//新增表单的验证规则
moreRules: {
  fieldSort: [{required: true, message: '请输入排序', trigger: 'change'},
    {
      validator: (rule, value, callback) => {
        if (value < 0) {
          callback(new Error('必须大于0'));
        } else if (value.length > 5) {
          callback(new Error('不超过5位数字'));
        } else if (!value) {
          callback(new Error('排序不能为空'));
        } else {
          callback();
        }
      },
      trigger: 'change',
    },
  ],
},
  • 这里需要注意的是:rules是每个表单都要都要添加的,有多个的话就要给每个表单绑定一个规则,也可以行内编写和对象形式
  • 另外要注意的是 :prop,正常表单验证单项是依靠prop,但是动态生成话要用 :prop

rules的写法和prop的写法见下面的代码

 <el-form-item label="描述"
	:prop="'powerAttrList.' + index + '.fieldName'"
	:rules="[{required: true, message: '描述不能为空',trigger: 'change'},{max: 32, message: '不超过32个字符', trigger: 'change'}]">
	<el-input v-model="item.fieldName" placeholder="请输入描述"/>
	</el-form-item>
	<el-form-item 
	label="排序"
	:prop="'powerAttrList.' + index + '.fieldSort'"
    :rules="moreRules.fieldSort">
    	<el-input type="number" v-model="item.fieldSort" placeholder="请输入排序"/>
    </el-form-item>

书写的语法是 :prop="'powerAttrList.' + index +'.fieldSort'"powerAttrList是v-for绑定的数组,index是索引,fieldSort是表单绑定的v-model的名称,然后用 . 把他们链接起来。

所以总结起来的语法就是 :prop="'v-for绑定的数组.' + index + '.v-model绑定的变量'"

接下来就是js的data里的表单数据

v-for绑定的数组也要在表单的对象里,写在表单对象外是验证不了的,需要在data里添加

formData3: {
    powerAttrList: [{
      fieldName: '',
      fieldSort: '',
      fieldDesc: '',
    }],
}

然后methods方法里新增属性列的函数应该这样写

 // 添加属性列
 addRow() {
   this.formData3.powerAttrList.push({
     fieldName: '',
     fieldShowName: '',
     fieldSort: '',
     fieldDesc: '',
     fieldType: '',
   });
 },

删除属性列的函数应该这样写

 // 删除属性列
 removeRow(index) {
    this.formData3.powerAttrList.splice(index, 1);
  },

全部代码贴上

注意前提是引用了element-ui哦

当然你们可以直接访问在线 demo

2020年补充:下面代码添加了下拉框和时间选择器的使用:
2021年补充:感谢评论老铁指出的错误,就是v-for循环 key 为index导致错误的验证提示,所以代码添加了唯一的key值取代数组索引index,所以最终代码如下

<template>
  <div>
    <el-form :model="formData3" :inline="true" ref="formData3" label-width="65px" size="medium">
      <el-row
        v-for="(item,index) in formData3.powerAttrList"
        :key="item.key"  // 更改前  :key="index"
        style="border-bottom: 1px solid #f0f0f0;padding: 10px;"
      >
        <el-form-item
          label="参数名"
          :prop="'powerAttrList.' + index + '.fieldName'"
          :rules="[{ required: true, message: '参数名不能为空',trigger: 'change'},{max: 32, message: '不超过32个字符', trigger: 'change'}]"
        >
          <el-input v-model="item.fieldName" placeholder="请输入参数名" />
        </el-form-item>
        <el-form-item
          label="时间"
          :prop="'powerAttrList.' + index + '.fieldTime'"
          :rules="[{ required: true, message: '时间不能为空',trigger: 'change'}]"
        >
          <el-date-picker
            v-model="item.fieldTime"
            type="daterange"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd"
            :default-time="['00:00:00', '23:59:59']"
          ></el-date-picker>
        </el-form-item>
        <el-form-item
          label="描述"
          :prop="'powerAttrList.' + index + '.fieldDesc'"
          :rules="[{ required: true, message: '描述不能为空',trigger: 'change'}]"
        >
          <el-select clearable v-model="item.fieldDesc" placeholder="请选择描述">
            <el-option
              v-for="item in options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item
          label="排序"
          :prop="'powerAttrList.' + index + '.fieldSort'"
          :rules="moreRules.fieldSort"
        >
          <el-input type="number" v-model="item.fieldSort" autocomplete="off" placeholder="请输入排序" />
        </el-form-item>
        <el-button
          type="danger"
          v-if="formData3.powerAttrList.length > 1"
          size="medium"
          @click="removeRow(index)"
        >删除</el-button>
      </el-row>
      <el-row>
        <el-button type="primary" size="medium" @click="addRow">新增属性</el-button>
        <el-button type="primary" size="medium" @click="submit('formData3')">提交</el-button>
      </el-row>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // select下拉项
      options: [
        {
          value: "选项1",
          label: "黄金糕"
        },
        {
          value: "选项2",
          label: "双皮奶"
        }
      ],
      formData3: {
        powerAttrList: [
          {
            fieldName: "",
            fieldSort: "",
            fieldDesc: "",
            fieldTime: "",
            key: Date.now() // 更改前没有
          }
        ]
      },

      // 新增表单的验证规则
      moreRules: {
        fieldSort: [
          { required: true, message: "请输入排序", trigger: "change" },
          {
            validator: (rule, value, callback) => {
              if (value < 0) {
                callback(new Error("必须大于0"));
              } else if (value.length > 5) {
                callback(new Error("不超过5位数字"));
              } else if (!value) {
                callback(new Error("排序不能为空"));
              } else {
                callback();
              }
            },
            trigger: "change"
          }
        ]
      }
    };
  },
  methods: {
    addRow() {
      this.formData3.powerAttrList.push({
        fieldName: "",
        fieldSort: "",
        fieldDesc: "",
        fieldTime: "",
        key: Date.now() // 更改前没有
      });
    },
    // 删除属性列
    removeRow(index) {
      this.formData3.powerAttrList.splice(index, 1);
    },
    // 提交
    submit(formName) {
      this.$refs[formName].validate(valid => {
        console.log(this.formData3);
        if (valid) {
          alert("submit!");
        } else {
          return false;
        }
      });
    }
  }
};
</script>
<style></style>
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值