2

How should I refer to the chart in a vue chart instance and destroy it? I've tried:

var chartVue = new Vue({
  el: '#chart',
  extends: VueChartJs.Line,
  data: {
    chartData: {...},
    options: {...}
  },
  mounted() {
    this.renderMyChart()
  },
  methods: { 
    renderMyChart: function() {
      this.renderChart(
        this.chartData,
        this.options
        );
    }
  },
  watch: {
    chartData: function() {
      this._chart.destroy();
      this.renderMyChart();
    }
  }
});

But it complains

TypeError: Cannot read property 'destroy' of undefined

So it seems this._chart is not the right way to refer to the current chart, anybody knows what is the right way to do this? The idea comes from this stack overflow answer.

Psidom
  • 209,562
  • 33
  • 339
  • 356
  • `this._chart` is the correct reference, so I'm not sure why it would be `undefined` at that point. But also, you can just use the `reactiveData` mixin, which does exactly what you're trying to do: http://vue-chartjs.org/#/home?id=reactive-data – thanksd Oct 25 '17 at 19:58
  • Hi @thanksd, thanks for the reply. I've looked into `mixin`s but not sure how to use it directly in a vue instance. The example shows how to use it in a vue component. Do you how how I can use reactiveProp here? – Psidom Oct 25 '17 at 20:04
  • 1
    Just add `mixins: [ VueChartJs.mixins.reactiveData ],`. And note that it does need to be `reactiveData` and not `reactiveProp` since you've defined `chartData` in your data object and not as a passed in prop. Example: https://jsfiddle.net/fuj4yqke/ – thanksd Oct 25 '17 at 20:08
  • @thanksd Excellent. I think that's the trick I am missing. I was trying `reactiveProp` all the time. It's working perfectly now. If you don't mind post as an answer, I'll upvote and accept it. The documentation does not seem very clear about this. – Psidom Oct 25 '17 at 20:13

2 Answers2

4

It seems this._chart has been moved to this._data._chart, so for instance to make the options reactive, add a watcher as follows:

watch: {
    options: function() {
        this._data._chart.destroy();
        this.renderChart(this.chartData, this.options);
    }
}
Psidom
  • 209,562
  • 33
  • 339
  • 356
2

The Chart object accessible via this._chart is not set until after the renderChart method is called. What's most likely happening is that your chartData is somehow being updated before that renderChart method has been called. So, the watcher for chartData is referencing this._chart before it has been defined.

However, vue-chartjs has a baked-in way to re-render the chart when the dependant data change: the reactiveData and reactiveProp mixins. By adding either of these mixins, the changes to the chartData (data-property or prop, respectively) will re-render the chart to reflect the updated data.

You should use the reactiveData mixin instead:

var chartVue = new Vue({
  el: '#chart',
  extends: VueChartJs.Line,
  mixins: [ VueChartJS.mixins.reactiveData ],
  data() {
    return {
      chartData: {...}, 
      options: {...}
    }
  },
  mounted() {
    this.renderChart(this.chartData, this.options);
  },
});
thanksd
  • 54,176
  • 22
  • 157
  • 150