9

I've several components using vue-tables-2 but one of them is not updating the table until I change the route.

component

    <template>
//..
    <div class="table-responsive" >
       <v-client-table ref="table" name="vCardTable" 
          :data="vCardTableData.data" 
          :columns="vCardTableData.headers" 
          :options="vCardTableData.options"/>
    </div> 
//..
    </template>
<script>
import { mapState } from "vuex";
import { mapGetters } from "vuex";

export default {
  name: "VCard",
  computed: {
    ...mapState("commons", ["user"]),
    ...mapGetters({ vCardTableData: "vCard/vCardTableData" })
  },
  mounted() {
    var self = this;
    self.$nextTick(() => {
      self.$store.dispatch("vCard/getVCards"); <-- GET TABLE DATA
    });
  }
};
</script>

store

const state = {
    vCardTableData: {
        data: [],
        headers: [
           //..
        ],
        options: {
            filterable: false,
            preserveState: false,
            headings: {
                //..
            },
            texts: {
                //..
            },
            pagination: {
                dropdown: true,
            },
            templates: {
                //..
            },
        },
    }
}

const getters = {
    vCardTableData: state => state.vCardTableData
}

const actions = {
    getVCards({commit, dispatch}) {
            return api.request("get", "getvcards").then(response => {
                setTimeout(() => {  
                    commit("setVCardTableData", response.data.vcards);
                }, 300);
            }).catch(error => {
                console.log(error);
            });
    }
}

const mutations = {
    clearTableData: (state) => {
        if (state.vCardTableData.data) {
            state.vCardTableData.data = [];
        }
    },
    setVCardTableData : (state, vCardTableData) => state.vCardTableData.data = vCardTableData   
}

As you can see in this image the table has data:

enter image description here But the view is refreshed when the route changes:

enter image description here

02/05/2018

Well now I've seen that if I modify the state directly in the component with promises it works:

this.$store.dispatch("vCard/getVCards", []).then((responseData)=>{
       this.$store.state.vCard.vCardTableData.data = responseData;
  }); 

Does anyone know why? Thank you

Fabio Venturi Pastor
  • 2,519
  • 3
  • 19
  • 32
  • may be because it requires some kind of "deep" tracking. look up that keyword with vuex. – A. L Apr 20 '18 at 12:43
  • try `useVuex=true` like `Vue.use(VueTables.ClientTable, [options = {}], [useVuex = true], [theme = 'bulma'], [template = 'default'])`, also I tested similiar codes as yours, it seems working fine.. – Sphinx Apr 27 '18 at 17:51
  • *"but one of them is not updating the table until I change the route."*, do you think it should change in response to what instead? Click of a button? Call of an action? If so, which one? – acdcjunior Apr 28 '18 at 01:32
  • Is calling an action -> self.$nextTick(() => { self.$store.dispatch("vCard/getVCards"); }); – Fabio Venturi Pastor May 02 '18 at 08:38

4 Answers4

2

My last answer was wrong, I did not remember that I had changed the vuex parameter of the table to false. I don't know why but doing a push it works:

setVCardTableData : (state, vCardTableData) => {
    vCardTableData.forEach(tableData => {
            state.vCardTableData.data.push(tableData);   
    });
} 
Fabio Venturi Pastor
  • 2,519
  • 3
  • 19
  • 32
1

This is a probably a reactivity issue. (See https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats for detailed explanation.)

Changing how you set the object value in your mutation to this should solve the problem

setVCardTableData: (state, vCardTableData) => state.vCardTableData = {
    ...state.vCardTableData,
    data: vCardTableData
}

Basically, this creates a new object so that Vue knows that the object has been updated. In Javasript, object is passed by reference, meaning that vCardTableData don't store the object, it stores the reference to the object. You could think of it as a pointer/address that points to the object in memory. When you change a child property in the object, the reference remains unchanged, so Vue does not know that the object has been updated. Creating a new object makes sure that the object reference is updated.

This is also explained in Mutations Follow Vue's Reactivity Rules in https://vuex.vuejs.org/en/mutations.html

tony19
  • 125,647
  • 18
  • 229
  • 307
Jacob Goh
  • 19,800
  • 5
  • 53
  • 73
1

I have had similar issues. Like others have already mention it is probably a reactivity problem. You can use Vue.set() to ensure that your properties are reactive when setting the state values.

setVCardTableData: (state, vCardTableData) => {
    Vue.set(state.vCardTableData, 'data', vCardTableData);
}

Check the official documentation for this method.

tony19
  • 125,647
  • 18
  • 229
  • 307
António Quadrado
  • 1,307
  • 2
  • 17
  • 34
0

Since it's a deep object, you need to use Object.assign in your mutation

setVCardTableData: (state, vCardTableData) => Object.assign(state.vCardTableData.data, vCardTableData)
Arielle Nguyen
  • 2,932
  • 1
  • 20
  • 15