I am working on a nuxt project and need to draw some charts. For that I use vue-chartjs as a plugin. Unfortunately the chart-data is fetched after the chart is drawn which results in an empty chart. I can't find a way to access the plugin and rerender the chart when the data is ready. Here is the code for the plugin:
// plugins/vue-chart.js
import Vue from 'vue'
import { Bar, Doughnut, Line, Pie } from 'vue-chartjs'
const registerComponent = function (name, originalComponent) {
Vue.component(
name,
{
extends: originalComponent,
props: ['data', 'options'],
mounted () {
this.renderChart(this.data, this.options)
},
updated () {
this.renderChart(this.data, this.options)
}
}
)
}
registerComponent('BarChart', Bar)
registerComponent('DoughnutChart', Doughnut)
registerComponent('LineChart', Line)
registerComponent('PieChart', Pie)
And here is how I use the plugin to draw a line chart:
components/Charts.vue
<template>
<client-only>
<LineChart :data="lineData" :options="options" />
</client-only>
</template>
<script>
export default {
data() {
return {
loading: true,
lineData: {
labels: [],
datasets: [
{
label: 'Close',
data: [],
},
{
label: 'High',
data: [],
},
],
},
options: {
responsive: true,
scales: {
x: {
display: true,
title: {
display: true,
},
},
y: {
display: true,
title: {
display: true,
text: 'Value',
},
},
},
},
}
},
async mounted() {
try {
const response = await this.$axios.get('/api/entries')
if (response.status === 200) {
for (let i = 0; i < response.data.length; i++) {
this.lineData.labels.push(response.data[i].date)
this.lineData.datasets[0].data.push(response.data[i].close)
this.lineData.datasets[1].data.push(response.data[i].high)
}
}
} catch (e) {
console.log(e)
}
},
}
</script>
I am happy about any suggestions on how to solve this!
Edit
I had to downgrade the versions of chart.js
and vue-chartjs
so that the project compiles.
Here is my package.json
{
"name": "xyz",
"version": "1.0.0",
"private": true,
"scripts": {
"dev-fe": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint": "npm run lint:js"
},
"dependencies":
"@nuxtjs/axios": "^5.13.6",
"chart.js": "^2.7.1",
"core-js": "^3.15.1",
"nuxt": "^2.15.7",
"vue": "^2.6.14",
"vue-chartjs": "^3.4.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.14.7",
"@nuxtjs/eslint-config": "^6.0.1",
"@nuxtjs/eslint-module": "^3.0.2",
"@nuxtjs/tailwindcss": "^4.2.0",
"eslint": "^7.29.0",
"eslint-plugin-nuxt": "^2.0.0",
"eslint-plugin-vue": "^7.12.1",
"postcss": "^8.3.5"
}
}
I use pretty much use the default in nuxt.config.js
except that I added
{ src: '~/plugins/vue-chart.js', mode: 'client' }
to the plugins.
Alright, I got a working example with the following.
Here is my
vue-chartjs.js
plugin/pages/index.vue
and my fake
.json
API data, because I didn't have an API to get some real dataI still mocked an API call, so it should work great as an example for you.
The idea behind this was to use the
key
hack, which is not really that good but eh, the maintainer is not really into helping people properly IMO.So this is still the best that is available.
Here is my final result and the related Github repo.