Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue-tables-2(vuex) reactivity not working

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

like image 213
Fabio Venturi Pastor Avatar asked Apr 20 '18 11:04

Fabio Venturi Pastor


2 Answers

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);   
    });
} 
like image 78
Fabio Venturi Pastor Avatar answered Oct 19 '22 19:10

Fabio Venturi Pastor


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

like image 1
Jacob Goh Avatar answered Oct 19 '22 21:10

Jacob Goh