Reputation: 1194
I've been stumped on getting my data to be reactive down to some chartjs charts.
I have a vuex store that when the app is mounted fires off an action to do some API cals (10 in total). Each API call is related to a department and it returns an array of all orders. That all works fine and I can see the data in vuex in the dev tools.
On my home page, I attempt to build 10 different charts. each chart has datasets related to a department's orders. The datasets are broken down to display late orders, on time, already shipped, etc.
So in my component that passes the data to the charts I use a state getter to fill out my data sets. So one of my getters is like this:
getDepartmentLateOrders: (state) => (department) => {
let resultArray = []
state[department].forEach(function(order, index) {
let now = new Date()
let orderShipDate = new Date(order.ExpectedShipDate)
let diff = date.getDateDiff(orderShipDate, now)
let statusCheck = outOfProductionStatuses
if(diff < 0 && !order.Invoiced && !statusCheck.includes(order.LastStatus)) {
resultArray.push(order)
}
})
return resultArray
Here is my store :
const store = new Vuex.Store({
state: {
//These are filled from setOrdersData()
dept1Orders: [],
dept2Orders: [],
dept3Orders: [],
loaded: false,
departmentsArray : ['dept1', 'dept2', 'dept3']
},
actions: {
//This is called when the app is mounted
loadOrders: function({ commit }) {
let departmentSeach = this.state.departmentsArray
departmentSeach.forEach(function(dept, index) {
api.getDeptStatus(dept.toLowerCase()).then((response) => {
store.commit('setOrdersData', { dept: dept, orders: response })
}, (err) => {
console.log(err)
})
})
this.state.loaded = true
}
},
mutations: {
//For reference: https://vuex.vuejs.org/en/mutations.html
setOrdersData: (state, payload) => {
Vue.set(state, payload.dept+'Orders', payload.orders)
},
},
getters: {
getDepartmentLateOrders: (state) => (department) => {
let resultArray = []
state[department].forEach(function(order, index) {
let now = new Date()
let orderShipDate = new Date(order.ExpectedShipDate)
let diff = date.getDateDiff(orderShipDate, now)
let statusCheck = outOfProductionStatuses
if(diff < 0 && !order.Invoiced && !statusCheck.includes(order.LastStatus)) {
resultArray.push(order)
}
})
return resultArray
},
getDepartmentShipTodayOrders: (state) => (department) => {
let resultArray = []
state[department].forEach(function(order, index) {
let now = new Date()
let orderShipDate = new Date(order.ExpectedShipDate)
let diff = date.getDateDiff(orderShipDate, now)
let statusCheck = outOfProductionStatuses
if(diff === 0 && !order.Invoiced && !statusCheck.includes(order.LastStatus)) { //TODO: Have this not exclude the out of production orders. But maybe have it highlight so it knows?
resultArray.push(order)
}
})
return resultArray
},
getDepartmentOutOfProductionOrders: (state) => (department) => {
let resultArray = []
let statusCheck = outOfProductionStatuses
state[department].forEach(function(order, index) {
if(statusCheck.includes(order.LastStatus) && !order.Invoiced) {
resultArray.push(order)
}
})
return resultArray
},
getDepartmentShippedOrders: (state) => (department) => {
let resultArray = []
//let statusCheck = ['SHIPPING-3']
state[department].forEach(function(order, index) {
if(order.Invoiced) {
resultArray.push(order)
}
})
return resultArray
},
getDepartmentOnTimeOrders: (state) => (department) => {
let resultArray = []
//let statusCheck = ['SHIPPING-3']
state[department].forEach(function(order, index) {
let now = new Date()
let orderShipDate = new Date(order.ExpectedShipDate)
let diff = date.getDateDiff(orderShipDate, now)
let statusCheck = outOfProductionStatuses
if(diff > 0 && !order.Invoiced && !statusCheck.includes(order.LastStatus)) {
resultArray.push(order)
}
})
return resultArray
},
}
})
Here is how I get to the data in the component that needs it:
fillData () {
let store = this.$store;
let departmentSeach = this.departmentArray
let that = this
departmentSeach.forEach(function(dept, index) {
console.log('get '+ dept)
that[dept+'DataCollection'] = Object.assign({}, that[dept+'DataCollection'],
{
datasets: [{
data: [
store.getters.getDepartmentShipTodayOrders(dept+'Orders').length,
store.getters.getDepartmentLateOrders(dept+'Orders').length,
store.getters.getDepartmentOutOfProductionOrders(dept+'Orders').length,
store.getters.getDepartmentShippedOrders(dept+'Orders').length,
store.getters.getDepartmentOnTimeOrders(dept+'Orders').length
//12, 13, 14, 15, 16
],
backgroundColor: that.defaultColors
}],
// These labels appear in the legend and in the tooltips when hovering different arcs
labels: that.defaultLables
})
})
this.loadingVisible = false
this.loaded = true
},
The problem is that my getters are running BEFORE all my API requests are completed. I had thought that this would be fine because it would be reactive, so as data came in and set the state data, the component that is using the getter would have data bound to it because I'm referencing the state getters that are using the state data.
On my initial charts page load, the charts don't render with the data, except the very first department (probably because the API call is fast enough). If I view a page in the app and go back to the charts page all my data is in there for the other departments and it works great.
So my question... what am I doing wrong in this example that the data is not being reactive? I'm sure it's some kind of reactivity gotcha that I am overlooking.
Upvotes: 0
Views: 1641
Reputation: 1194
So the main issue that this all was related to was how I instantiated my data for the charts. I set the empty department order objects in data
. However, the correct way of doing it is to use computed
instead because the data is derived from the store and will be reactive to the data as it comes in to my stores and the getters respond. After I did that everything worked just fine.
Upvotes: 1