Implementation of draggable rows and columns and selection column components based on el-table encapsulation

Implementation of draggable rows and columns and selection column components based on el-table encapsulation

Effect

Need environment

vue
elementUI
Drag and drop plugin Sortable.js

Required configuration properties

Example

<HTable
  :columns="columns"
  :data="list"
  :setColumn="true"
  tableKey="CategoriesList"
  style="width: 100%"
  border
>
  // You can put slots here <template slot="create_time" slot-scope="scope">
    {{ scope.column.label + scope.item.prop }}
  </template>
  <template slot="action" slot-scope="scope">
    <el-button type="primary" @click="handleEdit(scope.row)" size="small">
      Edit</el-button>
    <el-button @click="handleDelete(scope.row)" type="danger" size="small">
      Delete</el-button>
  </template>
</HTable>
import HTable from "@/components/HTable";

export default {
  components: { HTable },
  data() {
    return {
      list: [],
      columns: [
        {
          label: "ID", // description prop: "_id", // The unique value of the column. Must have checked: true // Whether to display this column... // Some el-table-column attributes can be written here},
        {
          label: "category name",
          prop: "name",
          checked: true
        },
        {
          label: "Superior Category",
          prop: "parent.name",
          checked: true
        },
        {
          label: "status",
          prop: "status",
          width: "100",
          checked: true
        },
        {
          label: "Creation time",
          prop: "create_time",
          slotHeaderName: "create_time", // Custom header checked: true
        },
        {
          label: "operation",
          prop: "action",
          fixed: "right",
          "min-width": "100",
          slotName: "action", // Custom cell slot checked: true,
          disabled: true
        }
      ]
    };
  }
};

Give me a thumbs up if it’s useful! Attached component code

<template>
  <div class="HTable">
    <div class="settingBox" v-if="setColumn">
      <el-popover
        placement="bottom-end"
        trigger="click"
        popper-class="settingPopper"
      >
        <el-checkbox-group
          v-model="selectCol"
          @change="handleChangeSelectColumn"
        >
          <el-checkbox
            v-for="item in col"
            :key="item.prop"
            :label="item.prop"
            :disabled="item.disabled"
            style="display:block;line-height:2;margin-right:0;"
            >{{ item.label }}</el-checkbox
          >
        </el-checkbox-group>
        <i class="icon el-icon-setting" slot="reference"></i>
      </el-popover>
    </div>
    <el-table
      v-bind="$attrs"
      :data="tableData"
      v-on="$listeners"
      :key="JSON.stringify(checkedCol)"
    >
      <el-table-column
        v-for="(item, index) in checkedCol"
        :key="item.prop"
        v-bind="item"
        :index="index"
        :column-key="item.prop"
      >
        <template v-if="item.slotHeaderName" v-slot:header="scope">
          <slot :name="item.slotHeaderName" v-bind="scope" :item="item"></slot>
        </template>
        <template v-if="item.slotName" v-slot:default="scope">
          <slot :name="item.slotName" v-bind="scope"></slot>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import Sortable from "sortablejs";
export default {
  name: "HTable",
  props: {
    tableKey: String,
    columns: {
      type: Array,
      default() {
        return [];
      }
    },
    data: {
      type: Array,
      default() {
        return [];
      }
    },
    setColumn: {
      type: Boolean,
      default: false
    }
  },
  watch:
    columns: {
      handler(newVal) {
        let localVal = this.getStorageCol();
        let hotVal = [];
        if (localVal) {
          hotVal = this.dataDiff(newVal, localVal);
        } else {
          hotVal = [...newVal];
        }
        this.col = hotVal.map(
          (item, index) =>
            (item = { ...item, index, checked: item.checked || false })
        );
        this.checkedCol = this.checkedColFun(this.col);
        this.selectCol = this.checkedCol.map(item => (item = item.prop));
      },
      immediate: true
    },
    data: {
      handler(newVal) {
        this.tableData = [...newVal];
      },
      immediate: true
    },
    col: {
      handler(newVal) {
        this.setStorageCol(newVal);
      },
      deep: true,
      immediate: true
    }
  },
  data() {
    return {
      tableData: [],
      col: [],
      checkedCol: [],
      selectCol: []
    };
  },

  mounted() {
    document.body.ondrop = function(event) {
      event.preventDefault();
      event.stopPropagation();
    };
    this.$nextTick(() => {
      this.rowDrop();
      this.columnDrop();
    });
  },
  methods: {
    drap() {
      this.$nextTick(() => {
        this.rowDrop();
        this.columnDrop();
      });
    },

    handleChangeSelectColumn() {
      this.col.forEach(item => {
        if (this.selectCol.includes(item.prop)) {
          item.checked = true;
        } else {
          item.checked = false;
        }
      });
      this.checkedCol = this.checkedColFun(this.col);
      this.drap();
    },

    rowDrop() {
      const tbody = document.querySelector(".el-table__body-wrapper tbody");
      Sortable.create(tbody, {
        onEnd: ({ newIndex, oldIndex }) => {
          [this.tableData[newIndex], this.tableData[oldIndex]] = [
            this.tableData[oldIndex],
            this.tableData[newIndex]
          ];
          this.drap();
          this.$emit("dropRow", {
            drapRow: this.tableData[oldIndex],
            targetRow: this.tableData[newIndex],
            drapRowIndex: oldIndex,
            targetRowIndex: newIndex,
            data: this.tableData
          });
        }
      });
    },
    columnDrop() {
      const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
      Sortable.create(wrapperTr, {
        animation: 180,
        delay: 0,
        onEnd: ({ newIndex, oldIndex }) => {
          const oldItem = this.checkedCol[oldIndex];
          const newItem = this.checkedCol[newIndex];
          [this.col[newItem.index].index, this.col[oldItem.index].index] = [
            oldItem.index,
            newItem.index
          ];
          this.col.sort((a, b) => {
            return a.index - b.index;
          });
          this.checkedCol = this.checkedColFun(this.col);
          this.tableData = this.tableData.slice(0, this.tableData.length);
          this.drap();
          this.$emit("dropCol", {
            colItem: oldItem,
            newIndex: newIndex,
            oldIndex: oldIndex,
            column: this.checkedCol
          });
        }
      });
    },
    checkedColFun(arr) {
      return arr.filter(item => item.checked);
    },
    setStorageCol(data) {
      if (this.tableKey && data && data.length > 0) {
        localStorage.setItem("HTable-" + this.tableKey, JSON.stringify(data));
      }
    },
    getStorageCol() {
      let datajson = localStorage.getItem("HTable-" + this.tableKey);
      return datajson ? JSON.parse(datajson) : "";
    },
    dataDiff(newVal, localVal) {
      let nl = newVal.length;
      let ll = localVal.length;
      if (nl != ll) {
        return newVal;
      } else {
        let np = newVal.map(item => item.prop).sort();
        let lp = localVal.map(item => item.prop).sort();
        if (np.join() != lp.join()) {
          return newVal;
        } else {
          let nnl = [];
          for (let i = 0; i < localVal.length; i++) {
            const item_l = localVal[i];
            for (let j = 0; j < newVal.length; j++) {
              const item_n = newVal[j];
              if (item_l.prop === item_n.prop) {
                nnl.push({
                  ...item_n,
                  index: item_l.index
                });
              }
            }
          }
          return nnl;
        }
      }
    }
  }
};
</script>

<style lang="less" scoped>
.HTable {
  position: relative;
  .settingBox {
    width: 36px;
    height: 36px;
    border-radius: 2px;
    border: 1px solid #ebeef5;
    border-bottom: 0;
    margin-left: auto;
    position: relative;
    .icon {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 1;
      width: 36px;
      height: 36px;
      text-align: center;
      font-size: 20px;
      line-height: 36px;
      color: #909399;
      cursor: pointer;
    }
  }
}
</style>
<style lang="less">
.settingPopper {
  min-width: 100px !important;
}
</style>

This is the end of this article about the implementation of draggable rows and columns and selection column components based on el-table encapsulation. For more relevant el-table draggable rows and columns, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of three ways to wrap text in el-table header
  • el-table in vue realizes automatic ceiling effect (supports fixed)
  • Vue+el-table realizes merging cells
  • vue perfectly realizes el-table column width adaptation
  • Secondary encapsulation of element el-table table (with table height adaptation)
  • vue uses sortable to implement el-table drag and drop sorting function
  • 4 ways to modify Element's el-table style in Vue
  • vue+element gets the subscript of a row in el-table and operates the array object according to the subscript
  • vue el-table implements custom table header
  • Vue el-table realizes inline editing function

<<:  【HTML element】How to embed images

>>:  Comprehensive summary of MYSQL tables

Recommend

Restart all stopped Docker containers with one command

Restart all stopped Docker containers with one co...

A brief discussion on what situations in MySQL will cause index failure

Here are some tips from training institutions and...

Keepalived implements Nginx load balancing and high availability sample code

Chapter 1: Introduction to keepalived The purpose...

How to write object and param to play flash in firefox

Copy code The code is as follows: <object clas...

A brief discussion on how to write beautiful conditional expressions in JS

Table of contents Multiple conditional statements...

Drawing fireworks effect of 2021 based on JS with source code download

This work uses the knowledge of front-end develop...

9 Practical Tips for Creating Web Content Pages

Content 1. Give readers a reason to stay. Make the...

Xhtml special characters collection

nbsp &#160; no-break space = non-breaking spa...

Notes on MySQL case sensitivity

Table of contents MySQL case sensitivity is contr...

Tutorial on installing php5, uninstalling php, and installing php7 on centos

First, install PHP5 very simple yum install php T...

Detailed explanation of the use of Vue's new built-in components

Table of contents 1. Teleport 1.1 Introduction to...

Common usage of hook in react

Table of contents 1. What is a hook? 2. Why does ...

How to write HTML head in mobile device web development

Copy code The code is as follows: <head> &l...

MySQL stored procedure in, out and inout parameter examples and summary

Stored Procedures 1. Create a stored procedure an...