el-table in element, type = 'expand' expand row, @ expand-change = & quot; & quot; event dynamic data refresh problem

Posted May 27, 20204 min read

Foreword

When writing a project recently, there is a functional requirement to use el-table embedded dynamic table, that is, table embedded table, and the table data inside is obtained dynamically, and the dynamic expansion is dynamically obtained

problem

According to the method in the element's table, the row attribute is set to type = 'expand', and @ expand-change = "expandChange" time is also added to the table to monitor the expansion row event, and the data is dynamically assigned to the expansion inside the monitoring time. table,
The problem arises, there is no data for the first click, only data for the second click
:The effect of the first click
Insert picture description here
:The second expanded data is displayed
Insert picture description here

solve

After seeing this, I actually know that it is caused by the asynchronous rendering of dom data(not echoed in time), so what should I do? So I started the process of self-try and temptation. During the process, I found that many friends also encountered such problems, and there were many ways:
1:Use this. $NextTick,
2:Use v-if to display hidden embedded tables,
3 ::There is no @ expand-change method --- changed to toggleRowExpansion control,
But in the end, these methods were more or less problematic. At that time, I was so confused that I did n t know what to do.

     When I rested at noon, there was a sudden flash of light. Since it is a problem of dom rendering, why do n t I add the data I need to this row of data first, and the dynamically obtained data is directly thrown in. Is this solved? Just do it:
     **First step**:The original settings remain unchanged, slightly change the expanded line

<el-table
      class = "common-table"
      :data = "tableData"
      style = "width:100%"
      stripe
      border
      @ expand-change = "expandChange"
    >
      <el-table-column type = "expand">
        <template slot-scope = "scope">
          <el-table:data = "scope.row.ruleItemData" border stripe style = "width:100%">
            <el-table-column prop = "questioncount" label = "Number of questions"> </el-table-column>
          </el-table>
        </template>
      </el-table-column>
      <el-table-column prop = "regionName" label = "region"> </el-table-column>
    </el-table>

Second step:Forcibly append a data item when obtaining data from an external table

//Get table data
    queryData() {
      rule.selectByPage(this.queryForm) .then(res => {
        if(res) {
          //Forcibly append a data item to each row of data
          res.content.list.map(item => {
            item.ruleItemData = [];
          });
          this.tableData = res.content.list;
        }
      });
    },

Third step:dynamically obtain the embedded table data, dynamically assign the current row

//Expand event-dynamically get embedded table data
    expandChange(row, expandedRows) {
      //This place is used to judge whether to expand or to collapse the line, only to make a request when expanding, to avoid multiple requests!
      //expandedRows has value when expanded, and empty when collapsed.
      if(expandedRows.length> 0) {
        rule
          .itemSelectByRuleID({
            examruleid:row.id
          })
          .then(res => {
            //Traverse the current page table
            this.tableData.forEach((temp, index) => {
              //Find the currently clicked line and assign the dynamically acquired data into it
              if(temp.id === row.id) {
                this.tableData [index].ruleItemData = res.content;
              }
            });
          });
      }
    }

This is perfect, no matter which row is clicked, which row of embedded table data is dynamically rendered.

Attach the simplified overall code for your reference

<template>
  <div class = "common-page">
    <el-table
      class = "common-table"
      :data = "tableData"
      style = "width:100%"
      stripe
      border
      @ expand-change = "expandChange"
    >
      <el-table-column type = "expand">
        <template slot-scope = "scope">
          <el-table:data = "scope.row.ruleItemData" border stripe style = "width:100%">
            <el-table-column prop = "questioncount" label = "Number of questions"> </el-table-column>
          </el-table>
        </template>
      </el-table-column>
      <el-table-column prop = "regionName" label = "region"> </el-table-column>
    </el-table>
  </div>
</template>

<script>
import {rule} from "@/api/api";
export default {
  data() {
    return {
      queryForm:{},
      tableData:[]
    };
  },
  created() {
    this.queryData();
  },
  methods:{
    //Get table data
    queryData() {
      rule.selectByPage(this.queryForm) .then(res => {
        if(res) {
          //Forcibly append a data item to each row of data
          res.content.list.map(item => {
            item.ruleItemData = [];
          });
          this.tableData = res.content.list;
        }
      });
    },
    //Expand event-dynamically get embedded table data
    expandChange(row, expandedRows) {
      //This place is used to judge whether to expand or to collapse the line, only to make a request when expanding, avoid multiple requests!
      //expandedRows has value when expanded, and empty when collapsed.
      if(expandedRows.length> 0) {
        rule
          .itemSelectByRuleID({
            examruleid:row.id
          })
          .then(res => {
            //Traverse the current page table
            this.tableData.forEach((temp, index) => {
              //Find the currently clicked line and assign the dynamically acquired data into it
              if(temp.id === row.id) {
                this.tableData [index].ruleItemData = res.content;
              }
            });
          });
      }
    }
  }
};
</script>

<style>
</style>

I hope it will be helpful to the small partners who encounter the same problem and get the job done!