場景:在項目的開發過程中,經常使用到表單中嵌套著可編輯的表格,這個時候就需要表單的雙重校驗。
本文栗子為二次封裝動態增減的可編輯表格,并實現表表單的雙重校驗
ps:由于實現的數據比較多,當前栗子為比較脫敏的,省略了一些字段,換湯不換藥。
子組件 variableList.vue
<template>
<article class="TPL_variable-list-container">
<el-form
ref="variableListForm"
:model="formData"
>
<el-table
v-show="formData.variableList.length"
:data="formData.variableList"
border
style="width: 100%"
class="form-item-content variable_tabel"
>
<!-- 變量-變量ID -->
<el-table-column
label="id"
class="table-item variable-item-id variable-id"
>
<template slot-scope="scope">
<el-form-item
:prop="`variableList.${scope.$index}.id`"
:rules="variableRules.id"
>
<el-input v-model.number="scope.row.id" class="table-item-content variable-id_input" />
</el-form-item>
</template>
</el-table-column>
<!-- 變量-變量名 -->
<el-table-column
label="name"
class="table-item variable-item-name variable-name"
>
<template slot-scope="scope">
<el-form-item
:prop="`variableList.${scope.$index}.name`"
:rules="variableRules.name"
>
<el-input v-model="scope.row.name" class="table-item-content variable-name_input" />
</el-form-item>
</template>
</el-table-column>
<!-- 變量-編輯 -->
<el-table-column
:label="variableLabels.operator"
class="table-item variable-item-operator variable-operator"
width="60"
>
<template slot-scope="scope">
<i class="el-icon-remove remove" @click="removeVariable(scope.$index)" />
</template>
</el-table-column>
</el-table>
</el-form>
<!-- 添加變量按鈕 -->
<el-link
class="form-item-content"
type="primary"
:underline="false"
icon="el-icon-circle-plus"
@click.native="addVariable"
>
添加變量
</el-link>
</article>
</template>
<script>
export default {
name: 'VariableList',
props: {
/**
* 父組件model必須為object
* 因為table中嵌套的form-item,所以table外層必須有el-form,el-form必須model,校驗才生效
* 且value默認傳入的variableList屬性,與table的綁定
* */
value: { type: Object, default: () => {} }
},
data () {
return {
formData: {
variableList: [] // 默認有該屬性,且該屬性名定義為variableList
},
variableRules: {
id: [{
required: true,
message: `請填入變量id`,
trigger: ['blur', 'change']
},
{
type: 'number',
message: '請輸入數字'
}],
name: [{
required: true,
message: `請填入變量名`,
trigger: ['blur', 'change']
}]
}
}
},
watch: {
value: {
immediate: true,
handler(newV) {
this.formData = newV
}
}
},
methods: {
// 添加變量
addVariable() {
const newVariable = {
id: '',
name: ''
}
this.pushVariable(this.formData.variableList, newVariable)
},
// 移除變量
removeVariable(id) {
this.spliceVariable(this.formData.variableList, id)
},
// 公共方法 - 添加變量
pushVariable(list, obj) {
list.push(obj)
},
// 公共方法 - 移除變量
spliceVariable(list, id) {
list.splice(id, 1)
}
}
}
</script>
子組件的使用
<template>
<el-form
ref="fatherForm"
:model="dataForm"
:rules="rules"'
:label-width="'120px'"
label-position="'right'"
class="TPL_deploy_form"
>
<el-form-item
label="name"
class="form-item item-space-name"
prop="name"
>
<el-input
v-model="dataForm.name"
class="form-item-content content_input name_input"
/>
</el-form-item>
<el-form-item
label="變量"
class="form-item item-variable"
>
<!-- deployTplForm 中必須有屬性variableList數組(子組件中自定義的,這里傳入的object需要包含該字段) -->
<!-- 使用子組件 :傳入一個ref用于校驗時獲取子組件校驗結果-->
<variable-list ref="childrenForm" v-model="dataForm" />
</el-form-item>
<!-- footer -->
<el-form-item class="form-item footer-conatiner">
<el-button
type="primary"
icon="el-icon-plus"
@click="OnSubmit"
>
提交
</el-button>
</el-form-item>
</el-form>
</template>
<script>
// 引入子組件
import variableList from '@/business/tmp/variableList/index.vue'
export default {
components: {
variableList
},
data() {
return {
dataForm: {
name: '',
variableList: []
},
}
},
methods: {
// 表單校驗:可用于多個表單同時校驗
getFormValidPromise(form) {
return new Promise((resolve, reject) => {
form.validate((res) => {
resolve(res)
})
})
},
// 提交表單
OnSubmit() {
const father_form = this.$refs.fatherForm // 父表單
// 獲取子組件的表單,childrenForm:使用子組件時傳的ref;variableListForm:子組件中el-form的ref
const children_form = this.$refs.childrenForm.$refs.variableListForm
Promise.all(
[father_form, children_form].map(this.getFormValidPromise)).then((res) => {
const validateResult = res.every(item => !!item)
if (validateResult) {
console.log('兩個表單都校驗通過')
} else {
console.log('兩個表單未校驗通過')
}
})
},
}
}
</script>
效果
image.png
image.png