HTF
HTF

Reputation: 7260

Vue.js with vue-chartjs - pulling data from API

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:

  1. 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?

  2. 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

Answers (1)

Jakub Juszczak
Jakub Juszczak

Reputation: 7827

  1. 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()

  2. 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

Related Questions