I am trying to visualize some data with Vue-d3-charts.
I am getting the data asyncronously with axios.
The problem is that i am having issues with pushing the response data to the chart_data.
Either i get the error that my variable(buildingdata) with the response is undefined (probably because the response arrives later than everything else and therefore ) or Error in callback for watcher "datum": "Error: too late; already running
.
Now i have confirmed that i am indeed getting a valid response by console logging the response to my browser.
What am i doing wrong?
Here is the vue code in my component
<template lang="pug">
div
.card
.card-body
//here is where the D3 component is
<D3BarChart :config="chart_config" :datum="chart_data" :title="chart_title"></D3BarChart>
</template>
<script>
import { D3BarChart } from 'vue-d3-charts';
import axios from "axios;
export default {
components: {
D3BarChart,
},
created(){
console.log("created function ran")
const sendGetRequest = async () => {
try {
let response = await axios.get("path_to_endpoint");
let buildingdata = response.data;
console.log(buildingdata)
//the code runs fine until i get here and try to push the response data to the chart_data.
this.chart_data.push(...buildingdata)
}
catch (error) {
console.log(error);
}
};
sendGetRequest();
},
data() {
console.log("data setup ran")
return {
chart_title: "Title",
// Chart data, this is where D3 gets its data from.
chart_data: [
],
// This is the chart config. it is from here you can change the chart type, colors, etc.
chart_config: {
key: 'name',
values: ['value'],
orientation: 'vertical',
},
}
},
}
</script>
Here is the output from my browser console
App mounted App.vue:35
data setup ran building.vue:36
created function ran building.vue:20
You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html vue.esm.js:9132
Array(5) [ {…}, {…}, {…}, {…}, {…} ]
[Vue warn]: Error in callback for watcher "datum": "Error: too late; already running"
found in
---> <D3BarChart>
<OpenWoPerBuilding> at app/javascript/apps/new_insights/components/open_wo_per_building.vue
<App> at app/javascript/apps/new_insights/App.vue
<Root> vue.esm.js:628
VueJS 15
_callee$ open_wo_per_building.vue:26
tryCatch app.js:221
_invoke app.js:221
defineIteratorMethods app.js:221
asyncGeneratorStep app.js:235
_next app.js:237
(Async: promise callback)
asyncGeneratorStep app.js:235
_next app.js:237
_asyncToGenerator app.js:237
_asyncToGenerator app.js:237
sendGetRequest open_wo_per_building.vue:21
created open_wo_per_building.vue:32
VueJS 41
js app.js:12
(Async: EventListener.handleEvent)
js app.js:9
Webpack 7
Error: too late; already running
set schedule.js:42
tweenFunction tween.js:31
__WEBPACK_DEFAULT_EXPORT__ each.js:5
__WEBPACK_DEFAULT_EXPORT__ tween.js:67
__WEBPACK_DEFAULT_EXPORT__ attrTween.js:43
__WEBPACK_DEFAULT_EXPORT__ attr.js:74
CodePudding user response:
So @kissu got me on the right track with the conditional rendering tip. What i did was use a flag that with a default of false in the "data()" that returns true after data has been fetched from axios in "created()".
<template lang="pug">
div(v-if="loaded")
.card
.card-body
<D3BarChart :config="chart_config" :loaded="loaded" :datum="chart_data" :title="chart_title"></D3BarChart>
</template>
<script>
import { D3BarChart } from 'vue-d3-charts';
import axios from "axios";
export default {
components: {
D3BarChart,
},
created(){
const sendGetRequest = async () => {
try {
let response = await axios.get("path_to_endpoint");
let buildingdata = response.data;
this.chart_data.push(...buildingdata)
this.loaded=true
}
catch (error) {
console.log(error);
}
};
sendGetRequest();
},
data() {
return {
loaded: false,
chart_title: "Title",
chart_data: [],
chart_config: {
key: 'name',
values: ['value'],
color: {name: '#7f3727'},
orientation: 'vertical',
},
}
},
}
</script>
CodePudding user response:
You need to wait to have some data before displaying your component. The reason being that the template is synchronous and is not waiting for your data to be fetched.
This can be solved with a small v-if
expecting your data to be fetched.
<D3BarChart v-if="asyncDataDoneLoading"
:config="chart_config"
:loaded="loaded"
:datum="chart_data"
:title="chart_title">
</D3BarChart>