哈喽,最近公司都在赶项目在做的过程中也踩了不少的坑。现在来记录下产品的需求:需要在表格中修改内容,并且对填入的数据进行校验后通过才可提交。我最终完成的效果如下图(主要涉及到表单的校验和表格行列合并):
主要思路
表单验证主要是通过 el-form的model 属性绑定对象 结合 el-form-item的prop和rules属性 外加 el-input的v-model绑定的值来进行触发验证。(其中 prop 的值是绑定v-model值的字段名,必须对应上否则无法触发 )
问题1: 后端返回的数据是数组中包含对象的格式(例如:[{},{},{}]),那如何给表单绑定model就是一个问题了,表单需要的是一个对象。解决方式:给数组多包一层(例如:Object:{array:[{},{},{}]})
问题2: 表格做表单校验需要对每个输入框都进行校验,那如何为每个输入框都添加验证也是个问题了。解决方式:动态绑定prop(例如: :prop="!array[${scope.$index}].rule.name
!" 注意,!是Es6模板语法的“`”)
问题3: 是使用 表单嵌套表格 还是 表格嵌套表单,这个也是个问题因为表单的校验触发不止只有通过点击输入之后才校验,在保存时是需要对全部的输入框都进行校验。 解决方式:使用表单嵌套表格的方式,这样可以通过 this.$refs.Form. validate()
来触发全部校验
下列为全部代码,不可直接运行会缺少样式和方法。仅供思考!
<template>
<div class="page-layout rataMdel">
<!-- 标题 -->
<div class="search-component">
<div class="header-flex">
<div class="tableTitle">商户四级七档评级标准</div>
<el-button type="primary" size="small" @click="edit" :plain="!editFlag">{{editFlag?'保存':'编辑'}} </el-button>
</div>
</div>
<!-- 表格 -->
<el-form ref="form" :model="currentTableDataObject">
<div class="Table-page" ref="table" >
<el-table ref="roleTable" v-loading="tableLoding" border stripe :data="currentTableDataObject.Arrays" :max-height='tableHight' :span-method="ObjectSpanMethod">
<template slot-scope="scope">
<el-table-column align="center" width="40" fixed>
<template slot-scope="scope">
{{scope.row.remark}}
</template>
</el-table-column>
<!-- 级别标准 -->
<el-table-column align="center" label="类型" width="400">
<template slot-scope="scope">
{{scope.row.name}}
</template>
</el-table-column>
<!-- 等级标准 -->
<el-table-column align="center" label="等级标准" width="250" >
<template slot-scope="scope">
<div v-if="!editFlag">{{scope.row.rule.name}}</div>
<div v-else>
<el-form-item :prop="`Arrays[${scope.$index}].rule.name`" :rules="[
{ required: true, message: '请输入标准', trigger: 'blur' }
]">
<el-input type="text" size="small" v-model.number="scope.row.rule.name" clearable placeholder="请输入标准"></el-input>
</el-form-item>
</div>
</template>
</el-table-column>
<!-- 相对分值 -->
<el-table-column align="center" label="分值" width="200" >
<template slot-scope="scope">
<div v-if="!editFlag">{{scope.row.rule.min}} - {{scope.row.rule.max}} 分</div>
<div v-else>
<el-form-item :prop="`Arrays[${scope.$index}].rule.min`" :rules="rules.grade_norm_min">
<el-input type="number" size="small" v-model.number="scope.row.rule.min" clearable class="small-num"></el-input>
</el-form-item>
<span>-</span>
<el-form-item :prop="`Arrays[${scope.$index}].rule.max`" :rules="rules.grade_norm_min">
<el-input type="number" size="small" v-model.number="scope.row.rule.max" clearable class="small-num"></el-input>
</el-form-item>
分
</div>
</template>
</el-table-column>
<!-- 商户标签(参考) -->
<el-table-column align="center" prop="member_label" label="备注说明" min-width="180px">
<template slot-scope="scope">
<p style="margin: 0">1."等级标准"名称与"分值"都可支持自定义设置;</p>
<p style="margin: 0">2.举例:若商户A满足商户交易属性为74分,金融属性88分,则商户A评级为一级1档</p>
</template>
</el-table-column>
</template>
</el-table>
</div>
</el-form>
</div>
</template>
<script>
import tabletext from '@/utils/tabletext.js'
import { checkIntNum0 } from '@/utils/regexp.js'
export default {
mixins: [tabletext],
data() {
return {
rules: {
grade_norm_min: [
{ required: true, message: '请输入数值', trigger: 'blur' },
{ validator: checkIntNum0, message: '错误数值', trigger: 'blur'}
]
},
page: 1,
tableData: {},
currentTableDataObject: {},
editFlag: false
}
},
methods: {
getTableData() {
let sendMessage = {
action: this.$api_lwj.getMemberRatingRuleList,
type: 0
}
this.tableLoding = true
this.$store.dispatch('Post', sendMessage).then((res) => {
setTimeout(()=>{
this.searchStopLoding()
}, 500)
this.tableData = res.data[0]
let currentTableData = []
// 由于后端返回的数据不符合前端的格式,所以进行了处理
Object.keys(this.tableData).forEach((item, index)=>{
for (let i = 0; i < this.tableData[item].rule.length ; i++) {
let tempJSON = {
title: item,
enable: this.tableData[item].enable,
name: this.tableData[item].name,
rate: this.tableData[item].rate,
remark: this.tableData[item].remark,
rule: this.tableData[item].rule[i]
}
currentTableData.push(tempJSON)
}
})
this.getSpanArr(currentTableData);
// 多套一层对象为了给form表单绑定对象,里面的数组是给table表格绑定的。 ——表单套表格
this.currentTableDataObject = {
Arrays: currentTableData
}
})
},
edit() {
if(this.editFlag){
this.$refs.form.validate((valid)=>{
if(valid){
let sendMessage = {
action: this.$api_lwj.updateMemberRatingRule,
rules: JSON.stringify(this.dealInfoData())
}
this.tableLoding = true
this.$store.dispatch('Post', sendMessage).then((res) => {
this.searchStopLoding()
if (res.data[0].sub_errno === '10000') {
this.$message({
type: 'success',
message: res.data[0].sub_errmsg
})
this.editFlag = false
this.getTableData();
}
})
}else{
this.$message({
type: 'warning',
message: '数据格式填写错误或为空'
})
}
})
}
this.editFlag = true
},
// 请求修改表单之前对数据进行再次处理。还原成后端需要的数据
dealInfoData(){
let tempArray = {}
this.currentTableDataObject.Arrays.forEach((item, index)=>{
let tempJSON = {
name: item.name,
enable: item.enable,
rate: item.rate,
remark: item.remark,
rule: [item.rule]
}
if(tempArray.hasOwnProperty(item.title)){
tempArray[item.title].rule.push(item.rule)
}else{
tempArray[item.title] = tempJSON
}
})
return tempArray
},
// 处理要合并相同行的列
getSpanArr (data) {
this.spanArr = []
for (var i = 0; i < data.length; i++) {
if (i === 0) {
// 如果是第一条记录(即索引是0的时候),向数组中加入1
/** *
* 例子:
* name:1
* name:1
* name:2
* name:2
* 最终结果:spanArr = [2,0,2,0]
*/
this.spanArr.push(1)
this.pos = 0
} else {
// 相同类型remark
if (data[i].name === data[i - 1].name) {
// 如果remark相等就累加,并且push 0
this.spanArr[this.pos] += 1
this.spanArr.push(0)
} else {
// 不相等push 1,并且pos 要换成当前下标
this.spanArr.push(1)
this.pos = i
}
}
}
},
ObjectSpanMethod({ row, column, rowIndex, columnIndex }){
// 合并相同列数据的行 第二列
if(columnIndex == 1){
const _row = this.spanArr[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
// 第一列合并
if(columnIndex == 0 ){
const _row = rowIndex == 0 ? 11 : 0
const _col = rowIndex == 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
// 最后一列合并
if(columnIndex == 4 ){
const _row = rowIndex == 0 ? 11 : 0
const _col = rowIndex == 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
}
},
created() {
this.getTableData();
}
}
</script>
<style rel="stylesheet/scss" lang="scss">
.rataMdel{
.el-table td{
padding: 6px 0;
}
.el-form-item__error{
display: none;
}
.header-flex{
display: flex;
align-items: center;
justify-content: space-between;
}
.tableTitle{
font-size: 20px;
margin-bottom: 30px;
}
.charts-box{
width: 100%;
display: flex;
justify-content: center;
}
.tableText{
padding: 15px;
font-size: 15px;
color: #333333;
}
.small-num{
display: inline-block;
width: 70px;
}
.small-string{
display: inline-block;
width: 130px;
}
p{
margin: 0;
padding: 0;
}
.el-form-item{
display: inline-block;
margin-bottom: 0px;
}
}
</style>
以上就是我对Element表格的理解,如果文章由于我学识浅薄,导致您发现有严重谬误的地方,请一定在评论中指出,我会在第一时间修正我的文章,以避免误人子弟。