element 动态表单多层级校验

288 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。(juejin.cn/post/705288… "juejin.cn/post/705288…

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'validate' o

这种报错是由于多层嵌套,prop 写错造成 image.png

一开始直接复制了element ui 上的模板没有修改 报错

image.png

小demo:

table.gif

data:

 dataInfo: {
        dynamicValidateForm: [
          {
            domains: [
              {
                value: "",
                name: ""
              }
            ]
          }
        ]
      }

methods:

 submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          alert("submit!");
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    removeDomain(item) {
      // 先找到在删除
      var index =  this.dataInfo.dynamicValidateForm[0].domains.indexOf(item);
      if (index !== -1) {
         this.dataInfo.dynamicValidateForm[0].domains.splice(index, 1);
      }
    },
    addDomain() {
      this.dataInfo.dynamicValidateForm[0].domains.push({
            value: "",
            name: ""
      });
    }

html:

<template>
  <div class="wrap">
    <el-form
      :model="dataInfo"
      ref="dynamicValidateForm"
      label-width="100px"
      class="demo-dynamic"
    >
      <div v-for="(item, index) in dataInfo.dynamicValidateForm" :key="index">
        <div v-for="(domain, idx) in item.domains" :key="idx">
          <el-row class="father">
            <el-col :span="6">
              <el-form-item
                :label="'域名' + index"
                :prop="
                  'dynamicValidateForm.' + index + '.domains.' + idx + '.name'
                "
                :rules="{
                  required: true,
                  message: '域名不能为空',
                  trigger: 'blur'
                }"
              >
                <el-input v-model="domain.name"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item
                :label="'name' + index"
                :prop="
                  'dynamicValidateForm.' + index + '.domains.' + idx + '.value'
                "
                :rules="{
                  required: true,
                  message: 'name不能为空',
                  trigger: 'blur'
                }"
              >
                <el-input v-model="domain.value"></el-input>
                <el-button class="btn"  @click.prevent="removeDomain(domain)"
                  >删除</el-button
                >
              </el-form-item>
            </el-col>
          </el-row>
        </div>
      </div>

      <el-form-item>
        <el-button type="primary" @click="submitForm('dynamicValidateForm')"
          >提交</el-button
        >
        <el-button @click="addDomain">新增域名</el-button>
        <el-button @click="resetForm('dynamicValidateForm')">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

样式:

<style lang="scss" scoped>
.wrap{
  padding-top: 20px;
  width: 1300px;
  margin-top: 200px;
  margin-left: 200px;
  border-radius: 10px;
  background-color: aliceblue;
  border: 1px solid aqua;
}
.father{
  position: relative;
}
.btn{
  position: absolute;
  right: -160px;
}
</style>

关键:

image.png 要注意每个层级的index

注意:

1.特别注意 prop 和 rules 的绑定, prop 里面的名称必须和输入框绑定的属性名称对应起来。 2. dattInfo 必须是一个对象,循环的是对象里面的 list 数组,往 list 数组里面动态增加数据。 3. 循环体里面再次添加动态的表单时,注意 idx 和外层 index 的区别。

源码:

<template>
  <div class="wrap">
    <el-form
      :model="dataInfo"
      ref="dynamicValidateForm"
      label-width="100px"
      class="demo-dynamic"
    >
      <div v-for="(item, index) in dataInfo.dynamicValidateForm" :key="index">
        <div v-for="(domain, idx) in item.domains" :key="idx">
          <el-row class="father">
            <el-col :span="6">
              <el-form-item
                :label="'域名' + index"
                :prop="
                  'dynamicValidateForm.' + index + '.domains.' + idx + '.name'
                "
                :rules="{
                  required: true,
                  message: '域名不能为空',
                  trigger: 'blur'
                }"
              >
                <el-input v-model="domain.name"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item
                :label="'name' + index"
                :prop="
                  'dynamicValidateForm.' + index + '.domains.' + idx + '.value'
                "
                :rules="{
                  required: true,
                  message: 'name不能为空',
                  trigger: 'blur'
                }"
              >
                <el-input v-model="domain.value"></el-input>
                <el-button class="btn"  @click.prevent="removeDomain(domain)"
                  >删除</el-button
                >
              </el-form-item>
            </el-col>
          </el-row>
        </div>
      </div>

      <el-form-item>
        <el-button type="primary" @click="submitForm('dynamicValidateForm')"
          >提交</el-button
        >
        <el-button @click="addDomain">新增域名</el-button>
        <el-button @click="resetForm('dynamicValidateForm')">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "",
  created() {},
  mounted() {},
  data() {
    return {
      // dynamicValidateForm: {
      //   obj:{
      //     domains: [
      //     {
      //       value: "",
      //       name:""
      //     }
      //   ]
      //   },
      //   email: ""
      // },

      // dynamicValidateForm: {

      //     domains: [
      //     {
      //       value: "",
      //       name:""
      //     }
      //   ],
      //   email: ""
      // }

      // dynamicValidateForm: {

      //     domains: [
      //     {
      //       value: "",
      //       name:""
      //     }
      //   ],
      //   email: ""
      // }
      dataInfo: {
        dynamicValidateForm: [
          {
            domains: [
              {
                value: "",
                name: ""
              }
            ]
          }
        ]
      }
    };
  },
  computed: {},
  methods: {
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          alert("submit!");
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    removeDomain(item) {
      // 先找到在删除
      var index =  this.dataInfo.dynamicValidateForm[0].domains.indexOf(item);
      if (index !== -1) {
         this.dataInfo.dynamicValidateForm[0].domains.splice(index, 1);
      }
    },
    addDomain() {
      this.dataInfo.dynamicValidateForm[0].domains.push({
            value: "",
            name: ""
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.wrap{
  padding-top: 20px;
  width: 1300px;
  margin-top: 200px;
  margin-left: 200px;
  border-radius: 10px;
  background-color: aliceblue;
  border: 1px solid aqua;
}
.father{
  position: relative;
}
.btn{
  position: absolute;
  right: -160px;
}
</style>