正文
先描述一下需求,看下图
1:动态合并行,如图所示,第一列全部合并,第二列和第三列第四列根据名称进行合并
2:可以动态编辑第三列和第四列,并且只能编辑属于此合并行的第三列和第四列,比如第一个编辑按钮点击后,只有前三行可以编辑
3:第一列的数据是根据第三列相加得来的
4:点击快捷填写,可以快速填写第三列和第四列
思路
1:第二列和第三列第四列根据名称进行合并
后台根据名称进行排序,前台通过循环解析名称来知道哪一行需要合并,这个从网上找了一个自己改了下。
第一列特殊情况根据上面的思路做简单修改
element代码: span-method="cellMerge"
<el-table border :data="tableData3" height="100%" width="100%" :cell-style="cellStyle" :row-style="getRowClass" :header-row-style="getRowClass" :header-cell-style="getRowClass" :span-method="cellMerge" >
vue代码:
//合并单元格,此方法需要后台进行名字进行排序 cellMerge({ row, column, rowIndex, columnIndex }) { let length = this.tableData3.length; //第0列比较特殊,单独合并 if (columnIndex === 0) { const _row = this.spanArrOne[rowIndex]; const _col = _row > 0 ? 1 : 0; return { rowspan: _row, colspan: _col }; } //1 2 5列进行合并 if (columnIndex === 1 || columnIndex === 2 || columnIndex === 5) { const _row = this.spanArr[rowIndex]; const _col = _row > 0 ? 1 : 0; return { rowspan: _row, colspan: _col }; } }, //1 2 5列合并的数据 getSpanArr(data) { for (var i = 0; i < data.length; i++) { if (i === 0) { this.spanArr.push(1); this.pos = 0; } else { // 判断当前元素与上一个元素是否相同 if (data[i].name === data[i - 1].name) { this.spanArr[this.pos] += 1; //需要合并的行数 this.spanArr.push(0); //新增被合并的行 } else { this.spanArr.push(1); this.pos = i; //新的需要合并的第几行数 } } } }, //0列合并的数据 getSpanArrOne(data) { for (var i = 0; i < data.length; i++) { if (i === 0) { this.spanArrOne.push(1); this.posOne = 0; } else { this.spanArrOne[this.posOne] += 1; //需要合并的行数 this.spanArrOne.push(0); //新增被合并的行 } } console.log(this.spanArrOne, " this.spanArrOne"); },
2:可以动态编辑第三列和第四列解决
添加template模块,里面添加input输入框和span标签,通过属性进行控制,我是通过取出后台数据,遍历后添加了自定义属性editing来控制的,为了只能编辑通过名称合并的第三列和第四列,我添加了属性flagNum,名字相同的行flagNum一样,我这边打印出来的是 0-2行是0 3到5行是3 6到9行是6以此类推,可以发现其规律就是第一个开头的行,当你点击第一个编辑按钮的时候,传的index就是0,所以根据flagNum匹配0-2行可以编辑,下面的是一样的逻辑
element代码;
<el-table-column prop="value1" label="XXX" min-width="15%" align="center"> <template slot-scope="scope"> <template v-if="scope.row.editing"> <el-input class="edit-input" v-model="scope.row.value1"></el-input> </template> <span v-else>{{ scope.row.value1 }}</span> </template> </el-table-column>
vue代码:
//判断可编辑作用域 用到的数据spanArr4Edit getSpanArr4Edit(data) { let ctx = this; var flagNum = 0; for (var i = 0; i < data.length; i++) { //首先不能编辑 ctx.$set(data[i], "editing", false); if (i === 0) { ctx.spanArr4Edit.push(flagNum); } else { // 判断当前元素与上一个元素是否相同 if (data[i].name === data[i - 1].name) { ctx.spanArr4Edit.push(flagNum); //还是同一个记录 } else { ctx.spanArr4Edit.push(i); flagNum = i; } } //与编辑相对应 ctx.$set(data[i], "flagNum", flagNum); } //最终赋值 ctx.tableData3 = data; console.log(ctx.spanArr4Edit, "this.spanArr4Edit"); }, handleEdit(index, row) { let ctx = this; this.setEditFlag(index, 1); console.log(index); }, /编辑输入框显示与隐藏0 隐藏 1显示 setEditFlag: function(index, flag) { let ctx = this; let datalength = ctx.tableData3.length; let flagNum = ctx.spanArr4Edit[index]; for (let i = 0; i < datalength; i++) { if (flag == 1) { if (flagNum === ctx.tableData3[i].flagNum) { //循环遍历改变可编辑的标记 this.$set(ctx.tableData3[i], "editing", true); } } else { //循环遍历改变可编辑的标记 this.$set(ctx.tableData3[i], "editing", false); } } }
3:第一列的数据是根据第三列相加得来的
可以用监听器深度监听后台传过来的数据
代码:
watch: { tableData3: { handler(newValue, oldValue) { let ctx = this; let length = oldValue.length; var num = 0; if (length > 0) { for (let i = 0; i < length; i++) { //取出编辑后的对象数据 num = Number(num) + Number(ctx.tableData3[i].value1); } if (num != 0) { //赋值对象数据 ctx.tableData3[0].all = num; } else { ctx.tableData3[0].all = ""; } } }, deep: true //深度监听对象里面的属性 } },
4:弹出个输入框
此逻辑比较简单,就是弹出个输入框,点击确认把值带到这个页面进行填写
直接上代码:
//快捷填写保存 addSubmit: function() { let ctx = this; //赋值数据,取出哪一行需要进行赋值 let idx = this.quickFlag; let datalength = ctx.tableData3.length; //每次快捷填写某一个区域,所以此变量在此定义 var initFlag = 0; for (let i = 0; i < datalength; i++) { if (idx === ctx.tableData3[i].flagNum) { if (initFlag == 0) { //value1 只赋值一次就行 this.$set(ctx.tableData3[i], "value1", this.addform.w); } initFlag++; this.$set(ctx.tableData3[i], "value2", this.addform.q); } } this.dialogQuick = false; ctx.$message.success("操作成功"); console.log(this.addform, "this.addform"); },
-----------------------------------分割线------------------------------------------------
完整代码
<template> <div class="waterApplyTable"> <el-table border :data="tableData3" height="100%" width="100%" :cell-style="cellStyle" :row-style="getRowClass" :header-row-style="getRowClass" :header-cell-style="getRowClass" :span-method="cellMerge" > <el-table-column prop="title" :label="title" align="center"> <el-table-column prop="all" label="xx" min-width="20%"> <template slot-scope="scope"> <span>{{ scope.row.all }}</span> </template> </el-table-column> <el-table-column prop="name" label="xx" min-width="15%" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="value1" label="xx" min-width="15%" align="center"> <template slot-scope="scope"> <template v-if="scope.row.editing"> <el-input class="edit-input" v-model="scope.row.value1"></el-input> </template> <span v-else>{{ scope.row.value1 }}</span> </template> </el-table-column> <el-table-column prop="value2" label="xx" min-width="15%" align="center"> <template slot-scope="scope"> <template v-if="scope.row.editing"> <el-input class="edit-input" v-model="scope.row.value2"></el-input> </template> <span v-else>{{ scope.row.value2 }}</span> </template> </el-table-column> <el-table-column prop="value3" label="xx" min-width="15%" align="center"></el-table-column> <el-table-column prop="editing" label="操作" min-width="20%" align="center"> <template slot-scope="scope"> <el-button type="primary" v-if="!scope.row.editing" @click.native="handleEdit(scope.$index, scope.row)" >编辑</el-button> <el-button type="primary" v-else @click.native="savemodify(scope.$index, scope.row)">保存</el-button> <el-button type="primary" @click.native="clickTodo(scope.$index, scope.row)">快捷填写</el-button> </template> </el-table-column> </el-table-column> </el-table> <el-dialog class="dialog" :visible="dialogQuick" top="15vh" @close="dialogQuickClose" width="20%" title="快捷填写" :append-to-body="true" > <el-form :model="addform" class="demo-form-inline"> <el-form-item label="x"> <el-input v-model.trim="addform.w"></el-input> </el-form-item> <el-form-item label="xx"> <el-input v-model.trim="addform.q"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click.native="addSubmit">确定</el-button> </div> </el-dialog> </div> </template> <script> export default { name: "waterApplyTable", props: { total: { type: Number, default: 100 } }, data() { return { rules: {}, page: 1, pageSize: 20, pageCount: 10, formInline: { area: "青岛市", year: "2018-2019" }, tableData3: [], dialogQuick: false, addform: {}, spanArr: [], pos: "", spanArrOne: [], posOne: "", spanArr4Edit: [], pos4Edit: "", //快捷填写flag,记录哪一行数据的快捷填写 quickFlag: "", title:'我是表头', }; }, watch: { tableData3: { handler(newValue, oldValue) { let ctx = this; let length = oldValue.length; var num = 0; if (length > 0) { for (let i = 0; i < length; i++) { num = Number(num) + Number(ctx.tableData3[i].value1); } if (num != 0) { ctx.tableData3[0].all = num; } else { ctx.tableData3[0].all = ""; } } }, //immediate: true, deep: true //深度监听对象里面的属性 } }, created() { this.getData(); }, mounted() { // this.getData(); }, methods: { getData() { this.getTableDataList(); }, // 列表, getTableDataList() { let ctx = this; // ctx.$api // .getTableDataList() // .then(res => { // ctx.total = res.totalRows; // ctx.pageCount = ctx.total / ctx.pageSize + 1; // ctx.tableData = res.rows; // }) // .catch(() => { // }); let _data = [ { all: "", name: "名字1", value1: "", value2: "", value3: "2017年-10月" }, { all: "", name: "名字1", value1: "", value2: "", value3: "2017年-11月" }, { all: "", name: "名字1", value1: "", value2: "", value3: "2017年-12月" }, { all: "", name: "名字2", value1: "", value2: "", value3: "2017年-10月" }, { all: "", name: "名字2", value1: "", value2: "", value3: "2017年-11月" }, { all: "", name: "名字2", value1: "", value2: "", value3: "2017年-12月" }, { all: "", name: "名字3", value1: "", value2: "", value3: "2017年-10月" }, { all: "", name: "名字3", value1: "", value2: "", value3: "2017年-11月" }, { all: "", name: "名字3", value1: "", value2: "", value3: "2017年-12月" }, { all: "", name: "名字4", value1: "", value2: "", value3: "2017年-10月" }, { all: "", name: "名字4", value1: "", value2: "", value3: "2017年-11月" }, { all: "", name: "名字4", value1: "", value2: "", value3: "2017年-12月" } ]; //进行赋值,为了后面编辑用,此方法位置不要动 ctx.getSpanArr4Edit(_data); console.log(ctx.tableData3, "ctx.tableData3"); ctx.getSpanArr(ctx.tableData3); ctx.getSpanArrOne(ctx.tableData3); }, //改变分页事件已办理 clickChangePage(currPage) { this.getGateStationList(currPage); }, cellStyle({ row, column, rowIndex, columnIndex }) { return "padding:0px"; }, getRowClass({ row, column, rowIndex, columnIndex }) { return "height:0"; }, searchData: function() { let searchVal = this.formInline.searchVal; }, setClass(gateState) { if (gateState == 0) { return "stateClass-a"; } return "stateClass-b"; }, dialogQuickClose: function() { this.dialogQuick = false; }, //前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性 //index 0开始 objectSpanMethod: function({ row, column, rowIndex, columnIndex }) { let length = this.tableData3.length - 1; // //合并第一列 // if (columnIndex === 0) { // console.log(columnIndex, "columnIndex"); // alert(columnIndex); // if (rowIndex % length === 0) { // return { // rowspan: length + 1, // colspan: 1 // }; // } else { // return { // rowspan: 0, // colspan: 0 // }; // } // } //合并第一列 if (columnIndex === 0) { alert(columnIndex); if (rowIndex % 2 === 0) { return { rowspan: 2, colspan: 1 }; } else { return { rowspan: 0, colspan: 0 }; } } //合并第二三列 }, //合并单元格,此方法需要后台进行名字进行排序 cellMerge({ row, column, rowIndex, columnIndex }) { let length = this.tableData3.length; //第0列比较特殊,单独合并 if (columnIndex === 0) { const _row = this.spanArrOne[rowIndex]; const _col = _row > 0 ? 1 : 0; return { rowspan: _row, colspan: _col }; } //1 2 5列进行合并 if (columnIndex === 1 || columnIndex === 2 || columnIndex === 5) { const _row = this.spanArr[rowIndex]; const _col = _row > 0 ? 1 : 0; return { rowspan: _row, colspan: _col }; } }, //1 2 5列合并的数据 getSpanArr(data) { for (var i = 0; i < data.length; i++) { if (i === 0) { this.spanArr.push(1); this.pos = 0; } else { // 判断当前元素与上一个元素是否相同 if (data[i].name === data[i - 1].name) { this.spanArr[this.pos] += 1; //需要合并的行数 this.spanArr.push(0); //新增被合并的行 } else { this.spanArr.push(1); this.pos = i; //新的需要合并的第几行数 } } } }, //0列合并的数据 getSpanArrOne(data) { for (var i = 0; i < data.length; i++) { if (i === 0) { this.spanArrOne.push(1); this.posOne = 0; } else { this.spanArrOne[this.posOne] += 1; //需要合并的行数 this.spanArrOne.push(0); //新增被合并的行 } } console.log(this.spanArrOne, " this.spanArrOne"); }, //编辑用到的数据 getSpanArr4Edit(data) { let ctx = this; var flagNum = 0; for (var i = 0; i < data.length; i++) { //首先不能编辑 ctx.$set(data[i], "editing", false); if (i === 0) { ctx.spanArr4Edit.push(flagNum); } else { // 判断当前元素与上一个元素是否相同 if (data[i].name === data[i - 1].name) { ctx.spanArr4Edit.push(flagNum); //还是同一个记录 } else { ctx.spanArr4Edit.push(i); flagNum = i; } } //与编辑相对应 ctx.$set(data[i], "flagNum", flagNum); } //最终赋值 ctx.tableData3 = data; console.log(ctx.spanArr4Edit, "this.spanArr4Edit"); }, //快捷填写 clickTodo: function(index, row) { this.dialogQuick = true; this.quickFlag = index; this.addform = {}; }, //快捷填写保存 addSubmit: function() { let ctx = this; //赋值数据,取出哪一行需要进行赋值 let idx = this.quickFlag; let datalength = ctx.tableData3.length; //每次快捷填写某一个分水口,所以此变量在此定义 var initFlag = 0; for (let i = 0; i < datalength; i++) { if (idx === ctx.tableData3[i].flagNum) { if (initFlag == 0) { //value1 只赋值一次就行 this.$set(ctx.tableData3[i], "value1", this.addform.w); } initFlag++; this.$set(ctx.tableData3[i], "value2", this.addform.q); } } this.dialogQuick = false; ctx.$message.success("操作成功"); console.log(this.addform, "this.addform"); }, handleEdit(index, row) { let ctx = this; this.setEditFlag(index, 1); console.log(index); // this.prevValue = JSON.parse(JSON.stringify(row));//保存之前的数据 }, handleCancle(index, row) { row.editing = false; // let prevContent = this.prevValue.bookname; // this.$set(row,"bookname",prevContent); }, savemodify(index, row) { this.setEditFlag(index, 0); console.log(row, "row"); console.log(this.tableData3, "改变后的table数据"); console.log( JSON.stringify(this.tableData3), "JSON.stringify(this.tableData3)" ); }, //提交数据到后台 submitToServe() { let ctx = this; let dataResult = JSON.parse(JSON.stringify(this.tableData3)); var result = 0; //调用后台保存方法 // ctx.$api.addWaterApply(dataResult).then(res => { // if (res.code == "0") { // result =1; // } // }); console.log(dataResult, "提交到后台的数据"); //return result; return 1; }, //编辑输入框显示与隐藏0 隐藏 1显示 setEditFlag: function(index, flag) { let ctx = this; let datalength = ctx.tableData3.length; let flagNum = ctx.spanArr4Edit[index]; for (let i = 0; i < datalength; i++) { if (flag == 1) { if (flagNum === ctx.tableData3[i].flagNum) { //循环遍历改变可编辑的标记 this.$set(ctx.tableData3[i], "editing", true); } } else { //循环遍历改变可编辑的标记 this.$set(ctx.tableData3[i], "editing", false); } } } }, filters: { iswarnFlt(val) { return val == 0 ? "否" : "是"; } } }; </script> <style lang="scss" scoped> .waterApplyTable { height: 100%; } </style>
以上就是Element Table行的动态合并及数据编辑示例的详细内容,更多关于Element Table行动态合并编辑的资料请关注阿兔在线工具其它相关文章!