Element Table dynamically merge rows and dynamically edit data

First describe the requirements, see the figure below

1: Dynamically merge rows, as shown in the figure, the first column is all merged, the second column and the third column and the fourth column are merged according to the name

2: You can dynamically edit the third and fourth columns, and you can only edit the third and fourth columns belonging to this merged row. For example, after the first edit button is clicked, only the first three rows can be edited

3: The data in the first column is based on the addition of the third column

4: Click Quick Fill, you can quickly fill in the third and fourth columns

Ideas

1: The second column and the third column and the fourth column are merged according to the name, and the background is sorted according to the name. The front desk knows which row needs to be merged by resolving the name. This I found one from the Internet and changed it myself.

 The first column of special cases is simply modified according to the above ideas

element code: 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 code:

//合并单元格,此方法需要后台进行名字进行排序
    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: You can dynamically edit the third and fourth columns to solve:

   Add template module, add input input box and span tag inside, control by attribute, I control by taking out background data, adding custom attribute editing after traversal, in order to only edit the third column and the first merged by name For four columns, I added the attribute flagNum, and the lines with the same name have the same flagNum. What I printed here is that lines 0-2 are 0, lines 3 to 5 are 3, lines 9 to 9 are 6, and so on, you can find the rule is The first line at the beginning, when you click the first edit button, the index passed is 0, so it can be edited according to the flagNum match 0-2 lines, the following is the same logic

element code;

 <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 code:

//判断可编辑作用域 用到的数据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: The data in the first column is based on the addition of the third column

You can use the listener to deeply monitor the data transmitted from the background

Code:

 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; This logic is relatively simple, that is, an input box pops up, click OK to bring the value to this page to fill in

Directly on the code:

  //快捷填写保存
    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");
    },

-----------------------------------Dividing line------------- -----------------------------------

Paste the complete code
 

<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>

 

Guess you like

Origin blog.csdn.net/CarryBest/article/details/90645082