[Chartjs]-Initialize a Chart.js chart with data from an api

1👍

The lifecycle hooks (like beforeCreate, etc.) don’t actually delay the subsequent component lifecycle steps, even when async, they just provide an entry point in which to run code.

Use a v-if to delay the rendering of the chart until the data is ready. The v-if acts like a watch and won’t render the chart at all until then. Use an isReady variable which you will set when the data is finished saving:

<Chart type="bar" v-if="isReady" :data="stackedData" :options="stackedOptions"/>
data()  {  
  return {
    isReady: false,
    ...
  }
}
axios.get(apiKaderURL).then(res => {
  this.all = res.data;
  this.saveData()
  this.isReady = true;  // Triggering the `v-if`
})

(Untested, but should work on principle)


Additionally, you can’t set a data property from another data property using this, it will be undefined. You can just set them to null:

data: this.list_all  // Does nothing, can't use `this` like that
data: null           // Change to this

So set it to null and fix the saveData method:

methods: {
  saveData() {
    const listAll = [];
    const listIntersection = [];

    for (var i in this.all){
      if(this.all[i].id==='2' ){
        listAll.push(this.all[i].someNumber)
      }
      if(this.all[i].id==='8'){
        listIntersection.push(this.all[i].someNumber) 
      }                     
    }
   
    this.stackedData.datasets[0].data = listAll;
    this.stackedData.datasets[1].data = listIntersection;
  }
}

2👍

I haven’t worked with Chart.js before, but I read through Installation, Integration, and Usage documentation and came up with an example that might help you (Vue 2 with Vue CLI).

I used my App.vue SFC as the parent of the child chart component ChartTest.vue. In the parent, I simulated an API call delay using a ‘setTimeout’ call in the ‘mounted’ hook.

App.vue

<template>
  <div id="app">
    <chart-test v-if="dataReady" :chartData="chartData" />
  </div>
</template>

<script>
  import ChartTest from '@/components/ChartTest'

  export default {
    name: 'App',
    components: {
      ChartTest
    },
    data() {
      return {
        chartData: [12, 19, 3, 5, 2, 3],
        dataReady: false
      }
    },
    methods: {
      getData() {
        this.dataReady = true;
      }
    },
    mounted() {
      // Simulate API call
      setTimeout(this.getData(), 2000);
    }
  }
</script>

ChartTest.vue

<template>
  <div class="chart-test">
    <h3>Chart Test</h3>
    <canvas id="my-chart" width="400" height="400" ref="chartref"></canvas>
  </div>
</template>

<script>
  import Chart from 'chart.js';

  export default {
    data() {
      return {
        myChart: null
      }
    },
    props: {
      chartData: {
        type: Array,
        required: true
      }
    },
    mounted() {
      this.myChart = new Chart(this.$refs.chartref, {
        type: 'bar',
        data: {
          labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
          datasets: [{
            label: '# of Votes',
            data: this.chartData,
            backgroundColor: [
              'rgba(255, 99, 132, 0.2)',
              'rgba(54, 162, 235, 0.2)',
              'rgba(255, 206, 86, 0.2)',
              'rgba(75, 192, 192, 0.2)',
              'rgba(153, 102, 255, 0.2)',
              'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
              'rgba(255, 99, 132, 1)',
              'rgba(54, 162, 235, 1)',
              'rgba(255, 206, 86, 1)',
              'rgba(75, 192, 192, 1)',
              'rgba(153, 102, 255, 1)',
              'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
          }]
        },
        options: {
          scales: {
            yAxes: [{
              ticks: {
                beginAtZero: true
              }
            }]
          }
        }
      });
    }
  }
</script>

Leave a comment