Reputation: 39
vue component won't wait for data from controller using axios get, it prompt error:
index.vue?d4c7:200 Uncaught (in promise) TypeError: Cannot read property 'ftth' of undefined
my code are below:
<template>
<div class="dashboard-editor-container">
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<line-chart :chart-data="lineChartData"/>
</el-row>
</div>
</template>
<script>
import LineChart from './components/LineChart';
import axios from 'axios';
const lineChartData = {
all: {
FTTHData: [],
VDSLData: [],
ADSLData: [],
},
};
export default {
name: 'Dashboard',
components: {
LineChart,
},
data() {
return {
lineChartData: lineChartData.all,
};
},
created() {
this.getData();
},
methods: {
handleSetLineChartData(type) {
this.lineChartData = lineChartData[type];
},
async getData() {
axios
.get('/api/data_graphs')
.then(response => {
console.log(response.data);
var data = response.data;
var i = 0;
for (i = Object.keys(data).length - 1; i >= 0; i--) {
lineChartData.all.FTTHData.push(data[i]['ftth']);
lineChartData.all.VDSLData.push(data[i]['vdsl']);
lineChartData.all.ADSLData.push(data[i]['adsl']);
}
});
},
},
};
</script>
Do I have to use watch method?
Upvotes: 1
Views: 16647
Reputation: 67
You can write dummy data in your data properties before real ones are loading
all: {
FTTHData: ["Loading..."],
VDSLData: ["Loading..."],
ADSLData: ["Loading..."],
},
Upvotes: 0
Reputation: 39
For the mean time:
Use set Axios Timeout 5000ms
axios
.get('/api/data_graphs', { timeout: 5000 })
.then(response => {
console.log(response.data);
var data = response.data;
var i = 0;
for (i = Object.keys(data).length - 1; i >= 0; i--) {
lineChartData.all.FTTHData.push(data[i]['ftth']);
lineChartData.all.VDSLData.push(data[i]['vdsl']);
lineChartData.all.ADSLData.push(data[i]['adsl']);
}
this.lineChartIsLoaded = true;
});
Use v-if in vue component
<line-chart v-if="lineChartIsLoaded" :chart-data="lineChartData" :date-data="dateData" />
Set lineChartIsLoaded to false at default
const lineChartIsLoaded = false;
Upvotes: 0
Reputation: 2073
First, because you have such a nested data structure you'll want a computed property to return whether the data is loaded or not. Normally, you could do this check in the template.
computed: {
isDataLoaded() {
const nestedLoaded = Object.keys(this.lineChartData).map(key => this.lineChartData[key].length !== 0)
return this.lineChartData && nestedLoaded.length !== 0
}
}
You can use v-if="isDataLoaded"
to hide the element until the data has been loaded.
Upvotes: 2
Reputation: 14201
It is not exactly clear how response.data
looks like, but because you're using Object.keys
I'm assuming it's an object.
If you need to loop over the keys then when using numeric indexes you most likely won't get an object. So you need to get the key
and index i
and use that value to access the object. Change this:
for (i = Object.keys(data).length - 1; i >= 0; i--) {
lineChartData.all.FTTHData.push(data[i]['ftth']);
lineChartData.all.VDSLData.push(data[i]['vdsl']);
lineChartData.all.ADSLData.push(data[i]['adsl']);
}
to this:
const keys = Object.keys(data)
for (i = keys.length - 1; i >= 0; i--) {
lineChartData.all.FTTHData.push(data[keys[i]]['ftth']);
lineChartData.all.VDSLData.push(data[keys[i]]['vdsl']);
lineChartData.all.ADSLData.push(data[keys[i]]['adsl']);
}
But for looping over object's keys is easier to use this:
for (let key in data) {
lineChartData.all.FTTHData.push(data[key]['ftth']);
lineChartData.all.VDSLData.push(data[key]['vdsl']);
lineChartData.all.ADSLData.push(data[key]['adsl']);
}
The alternative syntax will feed you keys and in my opinion is easier to read.
Upvotes: 1