Search code examples
vue.jsvue-chartjs

VueJS - vue-charts.js


I am trying to pass data I fetch from API to vue-chartjs as props, I am doing as in the documentation but it does not work.

Main component

<monthly-price-chart :chartdata="chartdata"/>

import MonthlyPriceChart from './charts/MonthlyPriceChart'

  export default {
    data(){
      return {
        chartdata: {
          labels: [],
          datasets: [
            {
              label: 'Total price',
              data: []
            }
          ]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false
        }
      }
    },
    components: {
      MonthlyPriceChart
    },
    created() {
      axios.get('/api/stats/monthly')
        .then(response => {
          let rides = response.data
          forEach(rides, (ride) => {
            this.chartdata.labels.push(ride.month)
            this.chartdata.datasets[0].data.push(ride.total_price)
          })
        })
        .catch(error => {
          console.log(error)
      })
    }
  }

In response I have an array of obejcts, each of which looks like this:

{
  month: "2018-10",
  total_distance: 40,
  total_price: 119.95
}

Then I want to send the data somehow to the chart so I push the months to chartdata.labels and total_price to chartdata.datasets[0].data.

chart component

import { Bar } from 'vue-chartjs'

export default {
  extends: Bar,
  props: {
    chartdata: {
      type: Array | Object,
      required: false
    }
  },
  mounted () {
    console.log(this.chartdata)
    
    this.renderChart(this.chartdata, this.options)
  }
}

console.log(this.chartdata) outputs my chartsdata object from my main component and the data is there so the data is passed correctly to chart but nothing is rendered on the chart.

The documentation says this:

<script>
import LineChart from './LineChart.vue'

export default {
  name: 'LineChartContainer',
  components: { LineChart },
  data: () => ({
    loaded: false,
    chartdata: null
  }),
  async mounted () {
    this.loaded = false
      try {
        const { userlist } = await fetch('/api/userlist')
        this.chartData = userlist
        this.loaded = true
      } catch (e) {
        console.error(e)
      }
  }
}
</script>

I find this documentation a bit vague because it does not explain what I need to pass in chartdatato the chart as props. Can you help me?


Solution

  • Your issue is that API requests are async. So it happens that your chart will be rendered, before your API request finishes. A common pattern is to use a loading state and v-if.

    There is an example in the docs: https://vue-chartjs.org/guide/#chart-with-api-data