处理多层级表单的提交,每个表单单独校验并收集表单数据

相信大家偶尔会遇到多层表单的情况,有时需要点击最外层的提交按钮,将每个tab栏下的表单全部校验并提交数据。这里抛砖引玉,简单介绍一下3层的表单处理思路,希望对你有所帮助。
最外层父组件:

<template>
  <div>
    <child :userInitData="userInitData"
           ref="childAll"
           @submitError="submitError">
    </child>
    <div @click="toSubmit">提交所有表单</div>
  </div>
</template>

<script>
import child from './child.vue'
export default {
  components: { child },
  data () {
    return {
      userInitData: []
    }
  },
  mounted () { },
  methods: {
    toSubmit () {
      // 验证人员信息表单
      if (this?.$refs?.childAll) {
        let params = { 'type': '1' }
        this.$refs.childAll.submit(params)
      }
    },
    submitError () {
      // 自定义 提交人员表单失败的逻辑
    }
  }
}
</script>

<style scoped lang="less"></style>

子组件:

<template>
  <div>
    <!-- 每个tab下面都是一个独立的表单 -->
    <el-tabs v-model="editTableValue"
             :closable="false"
             :addable="false"
             :editable="false"
             @tab-click="tabClick"
             @tab-remove="tabRemove">
      <el-tab-pane v-for="(item, index) in editObj.tabArr"
                   :key="'userInfoTab' + index"
                   :label="item.title"
                   :name="item.name">
        <grandSon :userInfoItem="item"
                  :ref="'userChildFrom' + index" />
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script>
import grandSon from './grandSon.vue'
export default {
  props: ['userInitData'],
  components: { grandSon },
  data () {
    return {
      editTableValue: '',
      editObj: {
        taskName: '',
        tabArr: [{
          'name': '用户1', 'title': '用户1'
        }, {
          'name': '用户2', 'title': '用户2'
        }, {
          'name': '用户3', 'title': '用户3'
        }, {
          'name': '用户4', 'title': '用户4'
        }, {
          'name': '用户5', 'title': '用户5'
        }]
      }
    }
  },
  mounted () { },
  methods: {
    submit () {
      if (this.$refs) {
        let userRefArr = []
        for (const key in this.$refs) {
          if (Object.hasOwnProperty.call(this.$refs, key)) {
            const eleItem = this.$refs[key]
            userRefArr.push(eleItem)
          }
        }
        // 这里可以使用refs获取到内部的每一个表单,并直接调用其validate方法,每个表单相互独立
        for (let i = 0; i < userRefArr.length; i++) {
          if (userRefArr[i] && userRefArr[i].length > 0 && userRefArr[i][0].userChildFrom) {
            userRefArr[i][0].$refs.userChildFrom.clearValidate()
            if (userRefArr[i][0]?.$refs?.userChildFrom) { // 表单的判空校验
              userRefArr[i][0].$refs.userChildFrom.validate((valid) => {
                if (valid) {
                  console.log(valid, '校验表单的属性')
                } else {
                  return false
                }
              })
            }
          }
        }
        // 校验成功后,书写提交的请求接口逻辑
      }
    },
    tabClick () { },
    tabRemove (targetVal) {
      const tabs = this.editObj.tabArr
      let activeTableVal = this.editTableValue
      if (activeTableVal === targetVal) {
        tabs.forEach((tab, index) => {
          if (tab.name === targetVal) {
            const nextTab = tabs[index + 1] || tabs[index - 1]
            if (nextTab) {
              activeTableVal = nextTab.name
            }
          }
        })
      }
      this.editTableValue = activeTableVal
      this.editObj.tabArr = tabs.filter(tab => tab.name !== targetVal)
    }
  }
}
</script>

<style lang="less" scoped>
// 自定义修改element tab的默认样式
/deep/.el-tabs__active-bar {
  background: none;
}

/deep/.el-tabs__nav-next {
  line-height: 0.36rem;
}

/deep/.el-tabs__nav-prev {
  line-height: 0.36rem;
}

/deep/.el-tabs__nav-wrap::after {
  display: none;
}

/deep/.el-tabs__item:hover {
  background: #00ddff;
  color: #041200;
  border-color: #00ddff;
}

/deep/.el-tabs__item.is-active {
  background: #00ddff;
  color: #041200;
  border-color: #00ddff;
}

/deep/.el-tabs__item {
  padding: 0.1rem;
  height: 0.36rem;
  line-height: 0.2rem;
  font-size: 0.14rem;
  font-family: Microsoft YaHei;
  font-weight: 400;
  color: #ffffff;
  opacity: 1;
  border: 1px solid #028888;
  border-right: none;
}

/deep/.el-tabs--top .el-tabs__item.is-top:nth-child(2) {
  padding-left: 0.1rem;
  border-radius: 2px 2px 2px 0;
}

/deep/.el-tabs--top .el-tabs__item.is-top:last-child {
  padding-right: 0.1rem;
  border-right: 1px solid #028888;
  border-radius: 0px 2px 2px 0px;
}

/deep/.el-tabs__new-tab {
  // 去除tab组件右侧的新增按钮
  display: none;
}

/deep/.el-tabs__header {
  margin-left: 0.1rem;
}
</style>

孙子组件:

<template>
  <div>
    <div class="child-tab-form">
      <el-form :model="userInfoForm"
               ref="userInfoForm"
               :rules="rules">
        <el-row>
          <el-col :span="24">
            <el-row class="head">
              <el-col :span="12">
                <div class="common-input-width padLeft18">
                  <span class="common-leftText-width">目的地</span>
                  <el-form-item label=""
                                prop="endTown">
                    <el-input class="common-select-block"
                              maxlength="50"
                              placeholder="请输入"
                              v-model="userInfoForm.endTown"></el-input>
                  </el-form-item>
                </div>
              </el-col>
              <el-col :span="12">
                <!-- 如果有多种情况分别展示,那么只有其中一种情况下的rules里的required生效 -->
                <div class="common-input-width"
                     v-if="userInfoForm.carType=='其他'">
                  <span class="common-rightText-width"><span class="label-must">*</span>具体类型</span>
                  <el-form-item label=""
                                prop="jtlx">
                    <el-select class="public-select common-select-block"
                               popper-class="public-select-popper"
                               v-model="userInfoForm.jtlx"
                               :multiple="false"
                               filterable
                               :collapse-tags="true"
                               placeholder="请选择">
                      <el-option v-for="item in jutiTypeArr"
                                 :key="item.value"
                                 :label="item.name"
                                 :value="item.value">
                      </el-option>
                    </el-select>
                  </el-form-item>
                </div>
                <div class="common-input-width"
                     v-else>
                  <span class="common-rightText-width"><span class="label-must">*</span>关联车辆</span>
                  <el-form-item label=""
                                prop="connectCar">
                    <el-input class="common-select-block"
                              maxlength="50"
                              placeholder="请输入"
                              v-model="userInfoForm.connectCar"></el-input>
                  </el-form-item>
                </div>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </el-form>
    </div>
  </div>
</template>
<script>
export default {
  props: ['userInfoItem'],
  data () {
    return {
      userInfoForm: {
        endTown: '',
        jtlx: '',
        connectCar: ''
      },
      rules: {
        endTown: [
          { required: true, message: '请输入目的地', trigger: 'blur' }
        ],
        jtlx: [
          { required: true, message: '请输入具体类型', trigger: 'change' }
        ],
        connectCar: [
          { required: true, message: '请选择关联车辆', trigger: 'blur' }
        ]
      }
    }
  },
  mounted () { },
  methods: {}
}
</script>

<style lang="less" scoped>
/deep/.el-input__inner {
  height: 0.32rem;
}
/deep/.public-input .el-textarea__inner {
  height: 0.74rem;
  color: #00ddff;
}
/deep/.el-textarea input::-moz-input-placeholder {
  color: #00ddff;
}
/deep/.el-textarea__inner::-webkit-input-placeholder {
  color: #00ddff;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值