Nested multiple selections based on tables in ElementUI (without pagination)

Preface:

I wrote this to help a friend fix a bug in a project

I am also the first time to write this function, there are wrong hope we correct, if there is help after reading a thumbs-up!

The key code is the js Tree path search this core, do not understand their own baidu

More not to say, there is a need can be private message to find me to code, see how I achieve

Ideas:

Looking at this requirement from the beginning, we need to know where to write things

  • Table 1
  • 2. Multiple selection & all selection
  • 3. Nested data (drop down operation)

It’s a good idea to check out the official ElementUI documentation

  • We found the API that we need to use
    • You need to use tree-props when nesting data
    • Use toggleRowSelection when selecting data

That’s pretty much all you can do with it

Implementation:

  • Based on this we can write the HTML structure
<template>
  <div>
    <el-table
      ref="multipleTable"
      :data="tableData"
      style="width: 100%; margin-bottom: 20px"
      row-key="id"
      border
      default-expand-all
      :select-on-indeterminate="true"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      @select="rowSelect"
      @select-all="selectAll"
    >
      <el-table-column type="selection" width="55"> </el-table-column>
      <el-table-column prop="date" label="Date" width="180"> </el-table-column>
      <el-table-column prop="name" label="Name" width="180"> </el-table-column>
      <el-table-column prop="address" label="Address"></el-table-column>
    </el-table>
  </div>
</template>
Copy the code

If checkout is true, then checkout in reverse. If checkout is false, checkout in reverse. If checkout is true, checkout in reverse

1. Forward selection

So let’s say I have data like this

Take figure 1 below as an example: When clicking the child node, we need to select the parent node and the child node at the same time. Figure 2 is the data declared in my data, including whether isChecked is selected and whether children have child nodesCopy the code

So now that we’re clear on the idea of selection how do we do that?

When I click on the child node, I need to record the parent node of the child node all the way to the following node, so we use the concept of a Tree

The following code uses the idea of Tree backtracking, to find the path to use the order traversal, because you are not sure you click on the child node is which child Tree, the specific Tree method idea please baidu;

treeFindPath(tree, func, path = []) {
      if(! tree)return [];
      for (const data of tree) {
        path.push(data);
        if (func(data)) return path;
        if (data.children) {
          const findChildren = this.treeFindPath(data.children, func, path);
          if (findChildren.length) return findChildren;
        }
        path.pop();
      }
      return [];
    },
Copy the code

With this code we pass the id of the node when we call it and it returns an array of objects in its path, so we can loop through the array and change the page state style using the toggleRowSelection antialgorithm.

Reverse cancellation

Reverse cancel is just the opposite of select

When clicking the child nodes to cancel we need to determine whether the node at the same level has been cancelled, if cancelled all need to change the parent of this node to cancel, then check its parent whether is cancelled at the state, if there are cancelled status, to its parent node in the same way and just the same way then find until does not meet the conditions, jump out of the loop.

  • Let me just draw a simple diagram

When clicking on node 4, it checks to see if peer nodes 5 and 6 are cancelled. If both are cancelled, check their upper level 2, change 2 to false, and check whether peer nodes 3 of 2 are cancelled. If cancelled, check 1

If the sibling is selected, it will jump out of the loop without going to the next step

  • Here is the deselect code

The array reverse() is flipped again using the Tree code

The first loop looks up from clicking on that node online

The for loop is used here to terminate the loop if it does not meet the requirements

Three, all

I feel a little wordy here,

I’m going to recursively check the data isChecked to see if any of them are selected

If it’s checked or not, it recursively changes isChecked to true for all the data, if it’s checked, it recursively changes it to false,

  • Below is a complete selection of all the code
        / * * *@describe If isAllCheck is false, */ is checked
    selectAll() {
      let isAllCheck = this.selectAllRecursion(this.outPool);
      this.checkoutAll(this.outPool, ! isAllCheck); },/ * * *@describe The recursion checks whether isChecked is true. False indicates whether */ isChecked
    selectAllRecursion(arr) {
      let isCheck = true;
      function isRecursion(arr) {
        arr.forEach((item) = > {
          if(! item.isChecked) { isCheck =false;
            if(item.children) { isRecursion(item.children); }}}); } isRecursion(arr);return isCheck;
    },
    / * * *@describe Select either true or false */
    checkoutAll(arr, boole) {
      function allCheck(arr, boole) {
        arr.forEach((item) = > {
          if (item.children) {
            allCheck.call(this,item.children, boole);
          }
          item.isChecked = boole;
          this.$refs.multipleTable.toggleRowSelection(item, boole);
        });
      }
      allCheck.call(this,arr, boole);
    },
Copy the code

The END:

That’s the basic code, no table paging

If there is a good way to write can tell me, there is a need to directly use the code can find me, if there is help remember to like