Vue-tables-2: Update an element in array doesn't refresh the table

Created on 17 May 2018  路  2Comments  路  Source: matfish2/vue-tables-2

  • Vue.js version: 2.5.16
  • consumed using: (browserify/webpack/rollup): webpack

I have this table:

<template>
  <v-client-table :data="tableData" :columns="columns" :options="options" v-on:update-row="onUpdateRow">
  </v-client-table>
</template>

<script>
  export default {
    data() {
      return {
        columns: ['id', 'prepared'],
        tableData: [],
        options: {
          templates: {prepared: Prepared}
        }
      }
    },
    methods: {
      onUpdateRow() {
        // Doesn't work. It doesn't seem to listen to event emitted in component column.
        console.log('onUpdateRow!');
      },
    },
    created() {
      this.$axios.get('admin/orders').then(({data}) => this.tableData = data);

      this.$root.$on('updateRow', rowData => {
        // Doesn't work.
        this.tableData[this.tableData.findIndex(el => el.id === rowData.id)] = rowData;

        // Works.
        this.tableData[this.tableData.findIndex(el => el.id === rowData.id)].prepared = rowData.prepared;

        // Works.
        this.tableData = [];

        // Works.
        this.tableData[1] = [];
      });
    }
  }
</script>

And this component:

<template>
  <button class="button is-small" @click="toggle()">
    <i v-if="data.prepared" class="fas fa-box"></i>
    <i v-else class="fas fa-box-open has-text-light"></i>
  </button>
</template>

<script>
  export default {
    props: ['data'],
    methods: {
      toggle() {
        this.$axios.patch(`admin/orders/${this.data.id}`, {prepared: (!this.data.prepared)})
          .then(({data}) => {
            // Doesn't work.
            // this.$emit('updateRow', data);
            // Use top most component as eventHub.
            this.$root.$emit('updateRow', data);
          })
        ;
      }
    }
  }
</script>
  • "prepared" is a boolean property of the elements containing in the array passed to the table.
  • Prepared is a component used to render the "prepared" column. It's a button a user can click to toggle the "prepared" value.

In the created() of the component containing the v-client-table, I get from API a list of elements and I keep it in this.tableData

When a user clicks on the "Prepared" button, I update the value in database (through api) and then I would like to refresh the element in the original array passed to the table with is freshest version so it will reflect on screen.
I'm thinking updating only the element modified by the user, not the whole array passed to the table.
I didn't know how to do that so maybe there is a better solution?
For now, I emit an event from the "Prepared" component and I listen to this event in the parent component (containing v-client-table) because it's there I can modify the original array passed to the table.

But I encounter these problems:

  1. in the "Prepared" component this.$emit('updateRow', data) is not listened to into the parent component. To solve that I use the top most component as event hub: this.$root.$emit('updateRow', data);
  2. so in the parent component I can listen to the event updateRow this way this.$root.$on('updateRow', rowData => {
  3. now in the handler of that listener I receive the last version of the element so I search for the element in the array and replace it but the vue-table doesn't refresh. If I delete (splice) the element or empty the table or modify only a property of an element, the vue-table refreshes.

What would be the appropriate way to solve this case?

Most helpful comment

Please add this to the documentation.

All 2 comments

OK, I found out I need to use Vue.$set(array, key, value) https://vuejs.org/v2/api/#Vue-set

Please add this to the documentation.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

singiankay picture singiankay  路  4Comments

dhdmstjs picture dhdmstjs  路  4Comments

molerat619 picture molerat619  路  4Comments

VladZen picture VladZen  路  4Comments

djokoabdullah picture djokoabdullah  路  3Comments