When using the Vue Array.splice() method, the DOM element is not removed in the element-ui table

I am facing an issue with a table containing hierarchical data in Vue. When attempting to remove a child using "array.splice", the DOM structure does not update reactively. Has anyone encountered this before? Are there any potential solutions?

This problem can be replicated using the example of a table on a Vuejs site.

var Main = {
    data() {
      return {
        tableData: [{
          id: 1,
          date: '2016-05-02',
          name: 'wangxiaohu'
        }, {
          id: 2,
          date: '2016-05-04',
          name: 'wangxiaohu'
        }, {
          id: 3,
          date: '2016-05-01',
          name: 'wangxiaohu',
          children: [{
              id: 31,
              date: '2016-05-01',
              name: 'wangxiaohu'
            }, {
              id: 32,
              date: '2016-05-01',
              name: 'wangxiaohu'
          }]
        }, {
          id: 4,
          date: '2016-05-03',
          name: 'wangxiaohu'
        }],
        tableData1: [{
          id: 1,
          date: '2016-05-02',
          name: 'wangxiaohu'
        }, {
          id: 2,
          date: '2016-05-04',
          name: 'wangxiaohu'
        }, {
          id: 3,
          date: '2016-05-01',
          name: 'wangxiaohu',
          hasChildren: true
        }, {
          id: 4,
          date: '2016-05-03',
          name: 'wangxiaohu'
        }]
      }
    },
    methods: {
      load(tree, treeNode, resolve) {
        resolve([
          {
            id: 31,
            date: '2016-05-01',
            name: 'wangxiaohu'
          }, {
            id: 32,
            date: '2016-05-01',
            name: 'wangxiaohu'
          }
        ])
      },
      removeRow(row){
        this.tableData[2].children.splice(0,1);
        //this.tableData.splice(0,1);
      }
    },
  }
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
@import url("//unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b5d0d9d0d8d0dbc198c0dcf5879b829b87">[email protected]</a>/lib/theme-chalk/index.css");
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="abcec7cec6cec5df86dec2eb99859c8599">[email protected]</a>/lib/index.js"></script>
<div id="app">
<template>
<div>
  <el-button @click="removeRow">
    Delete child
  </el-button>
  <el-table
    :data="tableData"
    style="width: 100%;margin-bottom: 20px;"
    border
    row-key="id">
    <el-table-column
      prop="date"
      label="日期"
      sortable
      width="180">
    </el-table-column>
    <el-table-column
      prop="name"
      label="name"
      sortable
      width="180">
    </el-table-column>
  </el-table>

  <el-table
    :data="tableData1"
    style="width: 100%"
    row-key="id"
    border
    lazy
    :load="load"
    >
    <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>
</div>
</template>
</div>

I am working with Vue 2.6.10 and element-ui 2.7.0

Answer №1

There appears to be an issue with how element-ui manages data internally. When directly modifying nested data, the table does not re-render (although the data is mutated correctly, as confirmed by logging this.tableData after using splice()).

A workaround is to create a copy of the tableData (requiring a workaround/polyfill for Array.from() in older browser support), make modifications to the copy, and then set tableData to the mutated version.

(To see the changes reflected, open the snippet in fullscreen mode, expand the children before clicking the button or click the button twice, as the children are initially collapsed and need to be re-rendered.)

// JavaScript code example
var Main = {
    data() {
      return {
        // Sample data for demonstration purposes
        tableData: [{
          id: 1,
          date: '2016-05-02',
          name: 'wangxiaohu'
        }, {
          id: 2,
          date: '2016-05-04',
          name: 'wangxiaohu'
        }, {
          id: 3,
          date: '2016-05-01',
          name: 'wangxiaohu',
          children: [{
              id: 31,
              date: '2016-05-01',
              name: 'wangxiaohu'
            }, {
              id: 32,
              date: '2016-05-01',
              name: 'wangxiaohu'
          }]
        }, {
          id: 4,
          date: '2016-05-03',
          name: 'wangxiaohu'
        }],
        tableData1: [{
          id: 1,
          date: '2016-05-02',
          name: 'wangxiaohu'
        }, {
          id: 2,
          date: '2016-05-04',
          name: 'wangxiaohu'
        }, {
          id: 3,
          date: '2016-05-01',
          name: 'wangxiaohu',
          hasChildren: true
        }, {
          id: 4,
          date: '2016-05-03',
          name: 'wangxiaohu'
        }]
      }
    },
    methods: {
      load(tree, treeNode, resolve) {
        resolve([
          {
            id: 31,
            date: '2016-05-01',
            name: 'wangxiaohu'
          }, {
            id: 32,
            date: '2016-05-01',
            name: 'wangxiaohu'
          }
        ])
      },
      removeRow(row){
        var newTableData = Array.from(this.tableData);
        newTableData[2].children.splice(0,1)
        this.tableData = newTableData;
        //this.tableData.splice(0,1);
      }
    },
  }
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
@import url("//unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6e0b020b030b001a431b072e5c4059405c">[email protected]</a>/lib/theme-chalk/index.css");
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9efbf2fbf3fbf0eab3ebf7deacb0a9b0ac">[email protected]</a>/lib/index.js"></script>
<div id="app">
<template>
<div>
  <el-button @click="removeRow">
    Delete child
  </el-button>
  <el-table
    :data="tableData"
    style="width: 100%;margin-bottom: 20px;"
    border
    row-key="id">
    <el-table-column
      prop="date"
      label="Date"
      sortable
      width="180">
    </el-table-column>
    <el-table-column
      prop="name"
      label="Name"
      sortable
      width="180">
    </el-table-column>
  </el-table>

  <el-table
    :data="tableData1"
    style="width: 100%"
    row-key="id"
    border
    lazy
    :load="load"
    >
    <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>
</div>
</template>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The positioning of the input is being altered by the bootstrap-vue formatter

Is there a way to replace whitespaces with underscores in the file name input of bootstrap-vue without changing the cursor position? If I add a white space not at the end of the input, the formatter moves the cursor to the end. How can I achieve this? I a ...

Having trouble with React testing-library: Why is the file upload empty when testing a PDF file?

While testing file upload with react-testing-library, I encountered an issue where the log indicated that the file was empty (even though it worked in the browser). After researching various docs and bugs, I discovered that since tests run on Node.js, the ...

Encountered a 'SyntaxError: await is only valid in async function' error while trying to utilize the top-level await feature in Node v14.14.0

I'm excited to use the new top-level await feature that was introduced in Node version 14.8. For more information, you can check out this link and here. I did a thorough search but couldn't find any questions related to issues with the new featur ...

What is the best way to create a "tile-based board" for this game?

I am working on a project to create a board made up of tiles, but I am facing difficulty in filling up the entire board area. Currently, I have only managed to create 1 column of the board, as shown in the image. Can someone guide me on how to fill the ent ...

Seems like the ng-show events inside are not being triggered, almost like an invisible image

I am encountering an issue where no JavaScript events are triggering inside an ng-show div in my code. You can access my code through the following link on Plnkr: http://plnkr.co/edit/kGqk8x?p=preview Upon loading data from JSON, I set ng-show to true. Ho ...

Tips for populating a 2D array with random colors using Java

I'm currently working on a brick-breaker game and have been attempting to create a grid of randomly colored boxes. However, each time I run the code, the colors keep changing which is not what I want. I would like the colors to be set randomly once an ...

Display the entire HTML webpage along with the embedded PDF file within an iframe

I have been tasked with embedding a relatively small PDF file within an HTML page and printing the entire page, including the PDF file inside an iframe. Below is the structure of my HTML page: https://i.stack.imgur.com/1kJZn.png Here is the code I am usin ...

How to find the set difference between arrays in C programming?

I'm currently working on a C program that consists of multiple functions. One function specifically requires me to calculate the set difference, which involves identifying elements present in set A but not in set B, and then storing these elements in ...

Can JavaScript be used to create a CSRF token and PHP to check its validity?

For my PHP projects, I have implemented a CSRF token generation system where the token is stored in the session and then compared with the $_POST['token'] request. Now, I need to replicate this functionality for GitHub Pages. While I have found a ...

What could be causing my vm root to be defined as app.__vue__?

I am facing an issue where my root vm in Vue is being set to app.__vue__ instead of just app. For instance, when trying to access the router, I have to use app.__vue__.$router. This seems unnecessary and confusing. There's more code in the script, bu ...

Utilize JavaScript on the browser to cache videos, potentially exceeding 10 minutes in length, directly

Currently, I am experimenting with WebRTC and looking to share a video stream with multiple peers. To optimize this process, I believe it would be beneficial to cache certain parts of the video. After exploring Cache Web APIs, I found them to be less effe ...

Retrieving data from a Java string array

I am currently developing a game where the player is required to input their first and last names. The program then extracts the first letters of both names and matches them with predefined names stored in an array. I suspect the issue lies in the latter ...

Could someone please guide me on how to use JQuery to set a radio button as checked?

<input type="radio" name="sort" value="2" id="myradio"> Is there a way to set this as the selected option using JQUERY? ...

Pattern matching for a string with numerous repetitions using Regular Expressions

There's a [tree] and a cat and a [dog] and a [car] too. I am looking to find the words inside each set of square brackets. The resulting array will be tree, dog, car My attempt at using match(/\[(.*)\]/g) didn't work as expected. It ...

What steps should I take to ensure that the buttons on my restaurant website are correctly displaying the overlays?

I'm currently facing an issue with the functionality of the buttons on my React.js-powered restaurant website. These buttons are located within a component called MenuButtons.jsx and are situated at the bottom of a shorter menu section on the homepage ...

Unraveling JSON data retrieved from a MySQL query

After successfully encoding a MySQL result from PHP into JSON, I am now faced with the task of decoding it using JavaScript. Let's assume that my string returned is: [{"0":"x","1":"z"},{"0":"xs","1":"zz"}] I would appreciate some guidance on how to ...

What could be causing my dropdown links to malfunction on the desktop version?

I've been developing a responsive website and encountering an issue. In desktop view, the icon on the far right (known as "dropdown-btn") is supposed to activate a dropdown menu with contact links. However, for some unknown reason, the links are not f ...

Axios issue: Cookies are not being transmitted

I have encountered an issue with a form built on Nuxt/vuejs and the backend side on django where CSRF protection is enabled. The API call now requires two things: X-CSRFToken as a header and csrftoken as a Cookie. I tested the API using Postman and it work ...

The JavaScript code that added links to the mobile menu on smaller screens is no longer functioning properly

I recently created a website with a mobile navigation menu that should appear when the browser width is less than 1024px. However, I used some JavaScript (with jQuery) to include links to close the menu, but now the site is not displaying these links and t ...

Choose the parent element along with its sibling elements

How can I target not only an element's siblings but also its parent itself? The .parent().siblings() method does not include the original element's parent in the selection. $(this).parent().addClass("active").siblings().removeClass("active"); I ...