0

I have a function in my vue applications that creates a chart.This is the chart function:

startChart: function (canvas, type) {

    // init chart.js
    var ctx = document.getElementById("myChart");
    var myDoughnut = new Chart(ctx, {
        type: 'doughnut',
        data: {
            labels: this.getAnalyticList[this.getRowIndex].chartNames,
            datasets: [{
                data: this.getAnalyticList[this.getRowIndex].chartData,
                backgroundColor: [
                    'rgba(255, 99, 132, 0.6)',
                    'rgba(54, 162, 235, 0.6)',
                    'rgba(255, 206, 86, 0.6)',
                    'rgba(75, 192, 192, 0.6)',
                    'rgba(153, 102, 255, 0.6)',
                    'red',
                    'yellow',
                    'blue',
                    'green',
                    'orange',
                    'teal',
                    'violet',
                    'pink',
                    'purple'
                ]
            }]
        },
        options: {
            responsive: true,
            defaultFontColor: '#ffffff',

        }
    })
}

and i then started it in the vue mounted hook using this line

this.startChart(this.$refs.canvas, 'Doughnut');

What i want to do is take the row index of a table loaded above the chart and that would then be passed into the getAnalyticList value that loads the charts so i can grab different arrays from the same list. I was working on creating an update function i got off this js fiddle from this stack article. I've been trying to adapt the function he created into vue but am having no luck here is the function:

changeData: function () {
            var myChart = Chart.doughnut(this.$refs.canvas, {
                data: data,
            });
            myChart.data.datasets.data = this.getAnalyticList[this.getRowIndex].chartData;
            myChart.data.labels = this.getAnalyticList[this.getRowIndex].chartNames;
            myChart.update();
        }

Any suggestions would be appreciated.

DanielM96
  • 103
  • 1
  • 3
  • 12
  • You may be interested in [vue-chartjs](https://github.com/apertureless/vue-chartjs). It's well tested and maintained, so you shouldn't have to do the integration yourself. – craig_h Aug 02 '17 at 14:35
  • unfortunately its not possible for this current project – DanielM96 Aug 02 '17 at 14:48

1 Answers1

2

I think the only problem with your code is that you're not updating the dataset correctly. With myChart.data.datasets.data = ... your adding data to datasets object - it should be myChart.data.datasets[0].data = ....

I've also added the chart object to Vue.js model in startChart with-out reactivity because it needs to be updated manually. Just don't add it to data hook. So you can reference the chart with this.myChart in your updating method.

I've renamed getRowIndex in the demo because rowIndex is more readable - you could do the same with the getAnalyticsLists. I would name it with get-prefix if it's a method that is getting something.

Scroll down in the demo to toggle the data with the next button. That button increments rowIndex and rolls over at the end.

Please have a look at the demo below or at this jsfiddle.

const chartComponent = {
  data() {
      return {
        //myChart: undefined, // don't add chart here -> reactivity could be a problem
        getAnalyticList: [{
          chartNames: [
            'Red',
            'Yellow',
            'Blue'
          ],
          chartData: [10, 20, 30]
        },
        {
          chartNames: [
            'Red',
            'Yellow',
            'Blue'
          ],
          chartData: [40, 10, 20]
        }
        ],
        rowIndex: 0
      }
    },
    template: `
    <div>
   <canvas id="myChart" width="200px" height="200px"></canvas>
    <button @click="incRow">next</button>
    {{rowIndex}}
    </div>
  `,
    methods: {
      startChart: function() {
        var ctx = document.getElementById("myChart");
        var myDoughnut = this.myChart =  new Chart(ctx, {
          type: 'doughnut',
          data: {
            labels: this.getAnalyticList[this.rowIndex].chartNames,
            datasets: [{
              data: this.getAnalyticList[this.rowIndex].chartData,
              backgroundColor: [
                'rgba(255, 99, 132, 0.6)',
                'rgba(54, 162, 235, 0.6)',
                'rgba(255, 206, 86, 0.6)',
                'rgba(75, 192, 192, 0.6)',
                'rgba(153, 102, 255, 0.6)',
                'red',
                'yellow',
                'blue',
                'green',
                'orange',
                'teal',
                'violet',
                'pink',
                'purple'
              ]
            }]
          },
          options: {
            responsive: true,
            defaultFontColor: '#ffffff',
      
          }
        })
      },
      incRow () {
       if (this.rowIndex < this.getAnalyticList.length - 1) {
         this.rowIndex++;
        }
        else {
         this.rowIndex = 0;
        }
        this.changeData()
      },
      changeData () {
       this.myChart.data.datasets[0].data =
         this.getAnalyticList[this.rowIndex].chartData;
        this.myChart.data.labels = this.getAnalyticList[this.rowIndex].chartNames;
        this.myChart.update();
        console.log('changed', this.myChart.data)
      }
    },
    mounted() {
      console.log('started')
      this.startChart();
    }
}

new Vue({
  el: '#app',
  components: {
    chart: chartComponent
  }
})
div {
   width: 400px;
   height: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js"></script>
<div id="app">
  <chart></chart>
</div>
AWolf
  • 8,770
  • 5
  • 33
  • 39