I use vue-chart.js
along with Vue2
to create a chart. I have a problem with passing API data to a chart. I use Vuex
store where I fetch data from API. There's a poor example on vue-chartjs.org showing how to handle an API. I also checked SO looking for an answer but in most cases renderChart()
placed in mounted()
is used, don't know if it's some workaround or proper way of dealing with this problem. I know that I need to pass Object instead of Array. I pass state directly to data , here :data="allSales"
. This is my problematic code which throws errors:
Invalid prop: type check failed for prop "data". Expected Object, got Array
Error in mounted hook: "TypeError: Cannot read properties of undefined (reading 'map')"
<template>
<v-container>
<v-row>
<v-col cols="6">
<Bar v-if="loaded"
id="my-chart-id"
:options="chartOptions"
:data="allSales"/>
</v-col>
</v-row>
</v-container>
</template>
<script>
import { mapActions, mapState } from 'vuex';
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
export default {
components: {
Bar
},
data() {
return {
chartOptions: {
responsive: true
},
loaded: false
}
},
computed: {
...mapState('custom', ['allSales'])
},
methods: {
...mapActions('custom', ['getAllSalesAction']),
},
mounted() {
this.loaded = false
try {
this.getAllSalesAction()
this.loaded = true
} catch (e) {
console.error(e)
}
},
}
</script>
EDIT: I add my Vuex store:
import axios from "axios";
const state = {
allSales: [],
};
const mutations = {
getAllSales: (state, all) => state.allSales = all,
};
const actions = {
async getAllSalesAction({commit})
{
const response = await axios.get(`https://localhost:44327/api/Commission/allData`)
commit('getAllSales', response.data)
},
};
export default {
namespaced: true,
state,
mutations,
actions,
};
Basically I have 2 questions:
Read carefully the documentation and notice how the data
prop of the Bar
component is of type Object
while you are feeding it with Array.
Follow the example from the documentation and use a Vuex getter instead of directly reading the state in order to generate the right data format:
const getters = {
getAllSales(state)
{
return {
labels: [ 'January', 'February', 'March'],
datasets: [
{
label: 'Data One',
backgroundColor: '#F87979',
data: state.allSales,
}
]
};
},
};