element's table multi selection combined with paging realizes the selected memory function and the dynamic synchronous update of table data and selected data

1. Effect drawing first:

1-1. No data at the beginning (equivalent to adding):

1-2: data at the beginning (equivalent to editing):

 

2. Main implementation logic:

With the help of the selection change method of the table of the element component (ps: table of element component )Combined with the paging component, you can define one for storing the checked data of the current page, one for storing all the checked data (that is, the checked data is displayed on the right), and one flag bit.

 

3. Specific code implementation:

3-1: HTML structure:

A: Illustration:

        

         

  B: Main code:

<div class="content-box flex-1">
              <div class="table-box h-p-100">
                <el-table
                  class="h-p-100"
                  ref="table"
                  border
                  stripe
                  highlight-current-row
                  @selection-change="handleSelectionChange"
                  :show-overflow-tooltip="true"
                  v-loading="table_loading"
                  :data="data ? data.rows : []"
                >
                  <el-table-column type="selection" width="40">
                  </el-table-column>
                  <el-table-column
                    label="Cover picture"
                    prop=""
                    width="120"
                    show-overflow-tooltip
                    header-align="center"
                    align="center"
                  >
                    <template slot-scope="{ row }">
                      <img
                        style="cursor: pointer; vertical-align: middle"
                        :src="globalimgUrl + downloadDir + row.cover + curToken"
                        width="90"
                        height="60"
                        v-viewer
                      />
                    </template>
                  </el-table-column>
                  <el-table-column
                    label="name"
                    prop="name"
                    min-width="180"
                    show-overflow-tooltip
                    header-align="center"
                  ></el-table-column>
                  <el-table-column
                    label="type"
                    prop="type"
                    width="80"
                    show-overflow-tooltip
                    header-align="center"
                  >
                    <template slot-scope="{ row, column, $index }">
                      <p v-if="row.type == 1">article</p>
                      <p v-if="row.type == 2">video</p>
                      <p v-if="row.type == 3">file</p>
                      <p v-if="row.type == 4">Series courses</p>
                    </template>
                  </el-table-column>
                  <el-table-column
                    label="classification"
                    prop=""
                    min-width="120"
                    show-overflow-tooltip
                    header-align="center"
                  ></el-table-column>
                  <el-table-column
                    label="Creator"
                    prop="createStaff"
                    width="120"
                    show-overflow-tooltip
                    header-align="center"
                  ></el-table-column>
                  <el-table-column
                    label="Update time"
                    prop="updateDate"
                    width="150"
                    show-overflow-tooltip
                    header-align="center"
                  ></el-table-column>
                </el-table>
              </div>
            </div>
            <div class="page-box ta-r uinn-t10 umar-r10 flex-0">
              <Page
                :show-total="true"
                :show-elevator="true"
                :show-sizer="true"
                :page-size="params.rows"
                :page-size-opts="[20, 50, 100, 150, 200]"
                :current="params.page"
                :total="data ? data.total : 0"
                @on-change="currentChange"
                @on-page-size-change="sizeChange"
              >
              </Page>
            </div>

3-2: JS logic:

A: Illustration:

 

 

 

 

 

 

B. Main code implementation:

import * as API from 'api/safety_learning/learn_management/train_plan';


export default {
   mixins: [tableMixin, permissionsMixin],
   props: {
      value: {
         type: Boolean,
         default: false
      },
      selectedEditData: {
         type: Array,
         default () {
            return []
         }
      }
   },
   data() {
      return {
         isShow: false, //Dialog box display and hide
         table_loading: false, //Table loading
         data: null, //List data
         multipleSelection: [], // Data selected on the current page
         idKey: "id", // The name of the unique key identifying each row in the list data (you need to change it according to your own data)
         selectedData: [], //The data of the selected course on the right (that is, all the selected data)
         params: {
            rows: 20,
            page: 1,
            name: "", //curriculum
            type: '', //type
         },
      }
   },
   watch: {
      value(bool) {
         this.isShow = bool
         if (bool) {
            if (this.selectedEditData && this.selectedEditData.length) {
               this.selectedData = this.selectedEditData;
            } else {
               this.selectedData = [];
            }
            this.curToken = '?access_token=' + getToken();
            this.getMinioBucketName().then(res => {
               this.index(1);
            })

         }
      }
   },
   methods: {
      // Set selected method
      setSelectRow() {
         if (!this.selectedData || this.selectedData.length <= 0) {
            return;
         }
         // The name of the unique key that identifies the current row
         let idKey = this.idKey;
         let selectAllIds = [];
         let that = this;
         this.selectedData.forEach(row => {
            selectAllIds.push(row[idKey]);
         });
         this.$refs.table.clearSelection();
         for (var i = 0; i < this.data.rows.length; i++) {
            if (selectAllIds.indexOf(this.data.rows[i][idKey]) >= 0) {
               // If the setting is selected, remember that the table component needs to use ref="table"
               this.$refs.table.toggleRowSelection(this.data.rows[i], true);
            }
         }
      },
      // Memory selection core method
      changePageCoreRecordData() {
         // The name of the unique key that identifies the current row
         let idKey = this.idKey;
         let that = this;
         // If there is no selected data in the total memory, the data selected on the current page will be taken directly without a series of subsequent calculations
         if (this.selectedData.length <= 0) {
            this.selectedData = this.multipleSelection;
            return;
         }
         // Always select the key set inside
         let selectAllIds = [];
         this.selectedData.forEach(row => {
            selectAllIds.push(row[idKey]);
         });
         let selectIds = [];
         // Gets the selected id of the current page
         this.multipleSelection.forEach(row => {
            selectIds.push(row[idKey]);
            // If the total selection does not contain the data selected on the current page, it will be added to the total selection set
            if (selectAllIds.indexOf(row[idKey]) < 0) {
               that.selectedData.push(row);
            }
         });
         let noSelectIds = [];
         // Get the id that is not selected on the current page
         this.data.rows.forEach(row => {
            if (selectIds.indexOf(row[idKey]) < 0) {
               noSelectIds.push(row[idKey]);
            }
         });
         noSelectIds.forEach(id => {
            if (selectAllIds.indexOf(id) >= 0) {
               for (let i = 0; i < that.selectedData.length; i++) {
                  if (that.selectedData[i][idKey] == id) {
                     // If there are unselected items in the total selection, delete this item
                     that.selectedData.splice(i, 1);
                     break;
                  }
               }
            }
         });
      },
      currentChange(val) {
         // Called once when the page is changed
         this.changePageCoreRecordData();
         this.params.page = val;
         this.index();
      },
      sizeChange(val) {
         // Called once when changing the number of display bars per page
         this.changePageCoreRecordData();
         this.params.rows = val;
         this.index();
      },
      //Get bucket name
      getMinioBucketName() {
         return new Promise((resolve, reject) => {
            this.isGetTm = false;
            API.getMinioBucketName().then((res) => {
               if (res.code !== 10000) return;
               this.isGetTm = true;
               this.downloadDir = res.data + '/';
               resolve(res);
            }).catch((err) => {
               this.isGetTm = true;
               reject(err)
            });
         })
      },
      //Select the change event in the table multi check box
      handleSelectionChange(val) {
         this.multipleSelection = val;
         setTimeout(() => {
            this.getRight();
         }, 50)
      },
      //You must call changePageCoreRecordData on multiple packages and call it in handleSelectionChange, otherwise there is bug.
      getRight() {
         this.changePageCoreRecordData();
      },
      //Delete selected (point X deletion event in the selected area on the right)
      delSelectedItem(id) {
         let row = this.data.rows.filter(i => {
            return i.id === id;
         });
         if (row && row.length) {
            this.$refs.table.toggleRowSelection(row[0]);
         }

         this.selectedData = this.selectedData.filter(i => {
            return i.id !== id;
         });
      },
      index(page) {
         $('#elTable .el-table__body-wrapper').scrollTop(0);
         if (page) {
            this.params.page = page;
         }
         let data = {
            org: this.analyseId,
            page: this.params.page,
            rows: this.params.rows,
            name: this.params.name,
            type: this.params.type,
         }

         this.table_loading = true;
         API.getclassesList(data).then(res => {
            this.table_loading = false;
            if (res.code === 10000) {
               this.data = {
                  total: res.total,
                  rows: res.rows
               };
               setTimeout(() => {
                  this.setSelectRow();
               }, 20);
            }

         }).catch(err => {
            this.table_loading = false;

         });
      },
      /**
       * Reset search
       */
      resetSearch() {
         for (let k of Object.keys(this.params)) {
            if (['page', 'rows'].includes(k)) {
               continue;
            }
            this.params[k] = '';
         }
         this.index(1);
      },
      //close
      cancel() {
         this.clear();
         this.$emit('cancelData');
      },
      //determine
      ok() {
         this.clear();
         this.$emit('getSelectedData', this.selectedData)
      },
      clear() {
         this.$emit('input', false);
      }
   },
};

 

4. Note: if this function effect is to be used in sub components (this work is implemented based on sub components), you need to pay attention to the following logic. Because the handleSelectionChange event will cause the selected data of the parent component (the variable passed from the parent component to the child component in this article is selectedEditData) to change synchronously when the child component is checked. No matter whether you click cancel or close after the child component is selected, the updated data will be brought back to the parent component. Very weird. Therefore, a solution is given here: when the parent component, first store the first selected data in the local cache, and then according to whether the child component clicks close (cancel) or saves different events transmitted to the parent component, and then the parent component makes different logical processing according to different events to ensure that the selectedEditData is accurate.

4-1. Main code implementation:

A. Illustration:

 

 

5. Summary: the above is a scheme for the table of elm component to realize paging selection memory function and selected data synchronization table operation. Please also have better and better children's boots. If this article is helpful, please connect more three times. Thank you.

 

Tags: Javascript Front-end Vue Vue.js elementUI

Posted on Wed, 01 Dec 2021 01:33:52 -0500 by drumhrd