vue-chartjs: Mixins don't seem to trigger a refresh of the chart

Expected Behavior

Adding a label and value to the dataset should add the item to the chart

Actual Behavior

Adding a label and value to the data doesn’t change the chart. The chart only gets redrawn when I resize the browser

Line chart:

import { Line, mixins } from 'vue-chartjs'

export default Line.extend({
  props: ["options", "chartData"],
  mixins: [mixins.reactiveProp],
  mounted () {
    this.renderChart(this.chartData,this.options);
    this._chart.update();
  },
})

Component:

<template>
    <div class="charts">
      <div class="col-md-12">
        <line-chart :chart-data="chartData" :options="chartOptions"></line-chart>
        <md-button @click.native="addData">add data</md-button>
      </div>
    </div>
</template>
<style scoped>
</style>
<script>
import lineChart from './chartOverviewTimeline.js';

export default {
    name: 'chartDashboard',
    components : {
        lineChart
    },
    data: function () {
        return {
          chartData : {},
          chartOptions : {mainAspectRatio : false}

        }
    },
    mounted(){
      this.prepareChartData();
    },
    methods: {
      addData: function(){
      for(let i = 0 ; i < 1; i ++){
          this.chartData.labels.push(100 + i);
          this.chartData.datasets[0].data.push(Math.random() * 100);
        }
      },
      prepareChartData(){
        this.chartOptions = {
          maintainAspectRatio:false,
          scaleShowHorizontalLines : true,
          scales: {
            xAxes: [{
              stacked: false
            }],
            yAxes: [{
              stacked: false,
              gridLines:{
                display: true
              }
            }]
          }
        };
        this.chartData = {
          labels:[],
          datasets:[
            {
              label: 'Sensor 1',
              backgroundColor: '#734375',
              data: [],
              fill: false,
              lineTension: 0
            }]
        };
        for(let i = 0 ; i < 5; i++){
          this.chartData.labels.push(i);
          this.chartData.datasets[0].data.push(Math.random() * 100);
        }
      }
    }    
}
</script>

I would expect that the addData function triggers a change in the prop and therefor a redraw in the chart.

Vue chartjs version 2.3.7

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 19 (7 by maintainers)

Most upvoted comments

Here’s my method, which IMO is the easiest solution, for parent to child component data.

First, assign your chart component a ref on the parent component. i.e. <radar-chart ref="radarChart" :data="radarChartData"></radar-chart>

In your chart component, I remove all reactive mixing stuff. Not needed. Then I created the following methods:

mounted () {
	this.renderChart(this.data, this.options)
},

methods: {
	update() {
		this.$data._chart.update()
	}
}

Finally, in your parent, create a method along of the lines of this to update your data:

updateDataExample() {
	this.radarChartData.datasets[0].data = [4, 2, 8, 6]
	this.$refs.radarChart.update()
},

I did like below and it is working reactively that way 😃

this.collection = Object.assign({})
  this.$set(this.collection,"labels",["Pojkar","Flickor","Kvinnor","Män"])
  this.$set(this.collection,"datasets",[])
  this.collection.datasets.push({
                            data: [this.pojkar, this.flickor, this.kvinnor, this.män],
                            backgroundColor: [
                                'rgba(255, 159, 64, 0.2)',
                                'rgba(54, 162, 235, 1)',
                                'rgba(155, 159, 64, 0.2)',
                                'rgba(255, 129, 64, 0.2)',
                            ],
                            borderColor: [
                                'rgba(255,99,132,1)',                        
                                'rgba(255, 206, 86, 1)',
                                'rgba(255, 206, 86, 1)',
                                'rgba(255, 206, 86, 1)',
                            ],
                            borderWidth: 1
                        
                    })

@thegreyfellow I believe it has to do with Vue itself and more deeply with JS in general, not with vue-chartjs. Changes like you describe are not identifyable, see Objects: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats Arrays: https://vuejs.org/v2/guide/list.html#Caveats

Particularly for array you can do array.splice(position, 1, new_datum)

Hi, i found what is a problem in, all in vue.$watch. When you change the object (not replacing), vue watch new value is the same as old, so i solve it by replacing object, but in your plugin there are a little issue, when you replacing object with the same dataset lenght, it’s give the chart.js update error. Thanks for attention, and sorry for my english.

Sorry to re-comment here but you should re-check the link you put on the docs it has an address of localhost:8080. I hope I’m not wrong

Thanks @quicky84 for the find. Additionally there is a note on vm.$watch

Note: when mutating (rather than replacing) an Object or an Array, the old value will be the same as new value because they reference the same Object/Array. Vue doesn’t keep a copy of the pre-mutate value.

I added it to the docs, I guess I can close here.