Modify the element-table yourself

Element’s Table component is well wrapped, but it can’t handle special needs. The project needed a header that could be dragged and dropped, so I came up with the idea that Element could use a slot to customize the header and manipulate it!

1. Project structure

For the Vue project (which will definitely install Element’s plugin), the template is shown below

<template>
  <div class="table-container">
    <el-table
      :data="tableData"
      height="250"
      border
      style="width: 100%"
    >
      <el-table-column
        :key="h.prop"
        v-for="h in tableHeaders"
        :prop="h.prop"
        :label="h.label"
        header-align="center"
        sortable
        draggable="true"
      >
        <template slot="header" slot-scope="{ column }">
          <span class="header-label" :id="h.prop">{{ column.label }}</span>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
Copy the code

The script section is shown below, because it is adapting Element’s own components. So it is not practical to use the normal vue @ event listener, so we use native JS to implement (jquery is also ok, all manipulation dom library is ok, I personally lazy to use native).

<script>
export default {
  name: "HelloWorld".methods: {
    handleSortClick(e, column) {},
    setCells() {
      setTimeout(() = > {
        let cells = document.querySelectorAll(".has-gutter th .cell");
        cells.forEach((cell, index) = > {
          cell.index = index;
          cell.draggable = true;
          cell.addEventListener("dragover".(e) = > {
            e.preventDefault();
          });
          cell.addEventListener("dragleave".(e) = > {
            e.target.style.border = "none";
          });
          cell.addEventListener("drop".(e) = > {
            e.preventDefault();
            let cell = e.path.find((p) = > p.className === "cell");
            if(! cell) {return;
            }
            cell.style.border = "none";
            if (this.target ! == cell) {let prop1 = this.target.children[0].id;
              let prop2 = cell.children[0].id;
              let index1 = this.tableHeaders.findIndex((h) = > h.prop === prop1);
              let index2 = this.tableHeaders.findIndex((h) = > h.prop === prop2);

              let temp = this.tableHeaders[index1];
              this.tableHeaders[index1] = this.tableHeaders[index2];
              this.tableHeaders[index2] = temp;
            }
            this.setCells();
            this.kd = Date.now();
          });
          cell.addEventListener("dragenter".(e) = > {
            let cell = e.path.find((p) = > p.className === "cell");
            if(! cell) {return;
            }
            if (this.target ! == cell) {setTimeout(() = > {
                if (this.target.index > cell.index) {
                  cell.style.borderLeft = "1px solid red";
                } else {
                  cell.style.borderRight = "1px solid red"; }},0); }}); cell.addEventListener("dragstart".(e) = > {
            // If the width is dragged, it will not trigger
            if (document.body.style.cursor === "col-resize") {
              this.target = {};
              return;
            }
            setTimeout(() = > {
              e.stopPropagation();
              if (this.target.toString() === "{}") {
                cell.style.backgroundColor = "#eee";
              }
              this.target = e.target;
            }, 0);
          });
          cell.addEventListener("dragend".(e) = > {
            cell.style.backgroundColor = "#fff";
            e.target.style.border = "none";
          });
          cell.addEventListener("mousedown".(e) = > {});
        });
      }, 0);
    },
    contextmenu(column, event) {
      event.preventDefault();
      console.log(column, event);
      let prop = column.property;
      // let index = this.tableHeaders.findIndex(h=>h.prop===prop)
      // this.tableHeaders.splice(index,1)}},mounted() {
    this.setCells();
  },
  data() {
    return {
      target: {},
      sortIndex: "0".kd: Date.now(),
      tableHeaders: [{prop: "date".label: "Date" },
        { prop: "name".label: "Name" },
        { prop: "address".label: "Address"},].tableData: [{date: "2016-05-03".name: "Wang Xiaohu".address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai}, {date: "2016-05-02".name: "Wang Xiaohu".address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai}, {date: "2016-05-04".name: "Wang Xiaohu".address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai}, {date: "2016-05-01".name: "Wang Xiaohu".address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai}, {date: "2016-05-08".name: "Wang Xiaohu".address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai}, {date: "2016-05-06".name: "Wang Xiaohu".address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai}, {date: "2016-05-07".name: "Wang Xiaohu".address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai,}]}; }}; </script>Copy the code

Here is the CSS part, which involves modifying the style of element, so I need /deep/, I am using SCSS preprocessor, if you need CSS, please change it yourself

<style lang="scss" scoped>
.table-container {
  padding: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  .header-label {
    padding: 10px 20px;
  }
}
/deep/ .el-table th > .cell {
  padding: 0;
}
/deep/ .el-table th {
  padding: 0;
}
</style>
Copy the code

Effect of 2.