1、此功能已集成到TTable组件中
2、最终效果
3、使用方式
1、第一种方式(全量配置,rules配置方式继承el-form)
table: {
rules: {
hobby: [{ required: true, message: '请至少选择一个爱好', trigger: 'change' }],
year: [{ required: true, message: '请选择年份', trigger: 'change' }],
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
},
....
}
2、第二种方式(单项配置(即在columns中某一项配置),rules配置方式继承el-form-item)
columns: [
{
prop: 'unit',
label: '单位',
minWidth: '220',
canEdit: true,
headerRequired: true,// 是否显示必填红点
configEdit: {
label: '单位',
append: '吨',
// 单项规则配置
rules: { required: true, message: '请输入单位', trigger: 'blur' },
bind: { 'prefix-icon': 'el-icon-search' },
editComponent: 'el-input'
}
},
]
3、校验错误提示(validateError事件)
注意:
1、必须是调用了save方法,才会触发validateError事件
2、validateError事件返回每项校验不通过的 label 集合——对应columns每项prop的label
4、具体实现
<!-- TTable组件 -->
<template v-if="item.canEdit">
<el-form
:model="tableData[scope.$index]"
:rules="isEditRules?table.rules:{}"
:ref="`formRef-${scope.$index}-${item.prop||scope.column.property}`"
>
<!-- 单个单元格编辑组件 -->
<single-edit-cell
:configEdit="item.configEdit"
v-model="scope.row[scope.column.property]"
:prop="item.prop"
:tableData="tableData"
:record="scope"
@handleEvent="(event,model) => $emit('handleEvent',event,model,scope.$index)"
@Keyup="handleKeyup"
v-on="$listeners"
v-bind="$attrs"
ref="editCell"
>
<!-- 遍历子组件非作用域插槽,并对父组件暴露 -->
<template v-for="(index, name) in $slots" v-slot:[name]>
<slot :name="name" />
</template>
<!-- 遍历子组件作用域插槽,并对父组件暴露 -->
<template v-for="(index, name) in $scopedSlots" v-slot:[name]="data">
<slot :name="name" v-bind="data"></slot>
</template>
</single-edit-cell>
</el-form>
</template>
<!-- single-edit-cell组件 -->
<template>
<el-form-item
:prop="record.column.property"
:rules="configEdit.rules"
:class="[configEdit.className,'single_edit_cell']"
v-bind="$attrs"
v-on="$listeners"
>
....
</el-form-item>
</template>
5、关键代码(save方法)
computed: {
// 单元格编辑是否存在校验
isEditRules() {
return (this.table.rules && Object.keys(this.table.rules).length > 0) || this.columns.some(item => item?.configEdit?.rules)
}
},
methods:{
// 单行编辑&整行编辑返回数据
save() {
if (!this.isEditRules) {
this.$emit('save', this.tableData)
return this.tableData
}
/**
* 表单规则校验
*/
let successLength = 0
let rulesList = []
let rulesError = []
let propError = []
let propLabelError = []
// 获取所有的form ref
const refList = Object.keys(this.$refs).filter(item => item.includes('formRef'))
// 获取单独设置规则项
const arr = this.renderColumns.filter(val => {
if (val.configEdit?.rules) {
return val
}
}).map(item => item.prop)
// 获取整体设置规则
const arr1 = this.table.rules && Object.keys(this.table.rules)
// 获取最终设置了哪些规则(其值是设置的--prop)
const newArr = [...arr, ...arr1]
// 最终需要校验的ref
newArr.map(val => {
refList.map(item => {
if (item.includes(val)) {
rulesList.push(item)
}
})
})
console.log('最终需要校验的数据', rulesList)
// 表单都校验
rulesList.map(val => {
this.$refs[val].map(item => {
item.validate((valid) => {
if (valid) {
successLength = successLength + 1
} else {
rulesError.push(val)
}
})
})
})
// 所有表单都校验成功
if (successLength === rulesList.length) {
if (this.isEditRules) {
this.$emit('save', this.tableData)
return this.tableData
}
} else {
// 校验未通过的prop
rulesError.map(item => {
newArr.map(val => {
if (item.includes(val)) {
propError.push(val)
}
})
})
// 去重获取校验未通过的prop--label
Array.from(new Set(propError)).map(item => {
this.renderColumns.map(val => {
if (item === val.prop) {
propLabelError.push(val.label)
}
})
})
console.log('校验未通过的prop--label', propLabelError)
this.$emit('validateError', propLabelError)
}
},
}
6、demo地址
GitHub源码地址
Gitee源码地址
相关文章
基于ElementUi或Antd再次封装基础组件文档
vue3+ts基于Element-plus再次封装基础组件文档
TTable组件封装地址