相信大家偶尔会遇到多层表单的情况,有时需要点击最外层的提交按钮,将每个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>