Reputation: 7260
I'm trying to use a similar approach to this project where labels
and datasets
are defined in a child component with binds to props in the parent component but I'm not getting any results.
"Vue.js devtools" add-on shows that props contain data passed in the parent component however the initial console log show empty arrays:
loadData init
Array []
Array []
So due to the fact that "Chart.js does not provide a live update if you change the datasets" I tried reactiveProp mixin which throws the error below, most likely because I'm updating only a single dataset:
Error in callback for watcher "chartData": "TypeError: newData.datasets is undefined"
Questions:
How the charts in this project from GitHub are updated if initially, bound arrays are empty and I don't see any related mixin or watcher?
How to use vue-chartjs
mixins to provide live updates in this case? I want to keep all the options and config in the chart component and just update the labels and datatsets.
components/LineChart.vue
<script>
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
//mixins: [reactiveProp],
props: {
chartData: {
type: Array | Object,
required: true
},
chartLabels: {
type: Array,
required: true
}
},
data () {
return {
options: {
responsive: true,
maintainAspectRatio: false,
legend: {display: false},
scales: {
xAxes: [{
display: false,
scaleLabel: {
display: false,
labelString: 'Date'
}
}],
yAxes: [{
stacked: false,
display: true,
scaleLabel: {
display: false,
labelString: 'Price'
},
ticks: {
beginAtZero: false,
reverse: false
}
}]
}
}
}
},
mounted () {
this.renderChart({
labels: this.chartLabels,
datasets: [{
label: 'Data One',
backgroundColor: '#18BC9C',
fill: true,
pointRadius: 0,
borderColor: '#18BC9C',
data: this.chartData,
}]
}, this.options)
}
}
</script>
App.vue
<template>
<div class="main">
<line-chart :chart-data="systemUptimeData" :chart-labels="systemUptimeLabels"/>
</div>
</template>
<script>
import LineChart from './components/LineChart'
export default {
name: 'Test',
components: {
LineChart
},
data: () => {
return {
systemUptimeLabels: [],
systemUptimeData: [],
}
},
methods: {
loadData () {
// This method will fetch data from API
console.log('loadData init', this.systemUptimeLabels, this.systemUptimeData)
this.systemUptimeLabels = ['a', 'b', 'c']
this.systemUptimeData = [1, 2, 3]
}
},
mounted () {
this.loadData()
}
}
</script>
<style scoped>
.main {
max-width: 800px;
max-height: 600px;
width: 100%;
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto;
}
</style>
Upvotes: 0
Views: 2707
Reputation: 7827
Well the reactivePropMixin
will not work in your example. Because it will only work if you pass the whole chart.js data object as a prop. Not only the data array for one dataset. It is quite limited. However you can simply add an own watcher and then call this.$data._chart.update()
The main problem with API requests is that they are async. So you component gets mounted, request the data and your chart gets rendered with no data, because your api call is maybe not finished at the time. Then it finishes, mutate your data and your chart will break. To prevent this it is a common practice to add a condition. In your promise or async call you need to define something like isLoaded
and if you finished the api call you can set it to true. And then add a condition to your chart v-if="isLoaded"
so your chart gets initially only rendered if you have your data from the API.
Upvotes: 1