I need to have Options be reactive so that it will update the title property. It does not appear to be watched in the mixin? No matter what I do below, the title will not re-render on the chart.
// lineChart.js
import { Line, mixins } from 'vue-chartjs'
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
// Nevermind the inconsistency that the "bar" component is delivering a "line" :)
// chart component
<template lang="pug">
.columns
.column.is-11.is-offset-1
.card
bar-chart(v-bind:chartData='chartData'
v-bind:options='chartOptions'
v-bind:height='340', v-bind:width='960' )
</template>
md5-891e9d135f1d388db18ea30b5309b3cf
I feel the same thing as you. Now I implement with the following way.
I hope it will be possible to watch options as mixins.reactiveProp
too.
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
watch: {
'options': {
handler(newOption, oldOption) {
this.renderChart(this.chartData, this.options)
},
deep: true
}
}
});
Euledge, thank you very much for helping. Unfortunately, when I change my chart code to include the watch and subsequent renderChart(), it is affecting the size of the chart (it appears to be doubling the size of the chart on each subsequent re-render). My chart js now looks like this:
import { Line, mixins } from 'vue-chartjs'
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
watch: {
'options': {
handler (newOption, oldOption) {
this.renderChart(this.chartData, this.options)
},
deep: true
}
},
mounted () {
this.renderChart(this.chartData, this.options)
}
})
Did I misinterpret your changes?
Thanks!
Hi @crholliday
Yeah the options are not reactive by default. But like @euledge pointed out, you can simply add a watcher by yourself.
You could try to call this._chart.update()
which is the internal chart.js method to update the chart instance. However I am not sure if this will work with options.
If this is not working, calling renderChart()
is the right way. But you should destroy the old instance before you do so. Because renderChart()
creates a new chartjs instance. Which could lead to weird problems.
import { Line, mixins } from 'vue-chartjs'
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
watch: {
'options': {
handler (newOption, oldOption) {
this._chart.destroy()
this.renderChart(this.chartData, this.options)
},
deep: true
}
},
mounted () {
this.renderChart(this.chartData, this.options)
}
})
I will see if I can implement it as a feature :v: so it will work out of the box
Hi @crholliday
I omitted the mounted block in the code, because I wrote complex processing on that block.
It's right as you wrote in mounted()
@apertureless
Thank you for show me destroy() is necessary.
Thanks Euledge and Apertureless... it is working now.
I can confirm, calling again renderChart was too buggy.
destroying before was the right solution.
The only difference is, I had to change a line
this.$data._chart.destroy();
Yeah due to the changes in v3
this._chart
is now this.$data._chart
When I update data in Vue form which Chart get the data nothing happens. Console logs nothing...
Vue.component('lineChartKw', {
extends: VueChartJs.Bar,
mixins: [mixins.reactiveProp],
props: ['chartData'],
watch: {
'chartData': {
handler (newOption, oldOption) {
console.log('refresh watcher')
this.$data._chart.destroy()
this.renderChart(this.chartData,{
responsive: true,
maintainAspectRatio: true
})
},
deep: true
}
},
mounted() {
if (this.chartData) {
this.renderChart(
this.chartData, {
responsive: true,
maintainAspectRatio: true
})
}
}
});
This is how data
looks (and I update only data
in first datasets
):
patterndatakw: {
labels: ['Backend', 'Full Stack', 'Mobile/Embedded', 'Testing', 'Frontend', 'Dev Ops', 'Business Intelligence', 'IT Trainee', 'Project Management', 'Support', 'UX Designer', 'Business Analyst', 'Other'],
datasets: [{
label: 'Refair.me Profile ',
backgroundColor: '#a84979',
data: [0.05, 0.2, 0.1, 0.5, 0.2, 0.05, 0, 0, 0, 0, 0]
}]
}
For now it only works if I update whole patterndatakw
.
@janswist
Well, but you are talking now about your data, right? Not about your options.
Because this issue is about the options.
There are a ton of other issues, regarding the reactivity of data.
First of all, you are importing the reactivity mixin but overwriting it in your local component. The mixin, will check of changes, and depending on the changes it will either update()
the chart or do a complete rerender.
It depends on how you are updating your data.
http://vue-chartjs.org/#/home?id=limitations
There are some limitations in javascript and vue, how to detect changes and what the watcher can detect.
I think destroying the chart then render again is not a good behavior.
This should work as expected.
export default {
extends: Line,
props: ['chartData', 'options'],
watch: {
options: {
handler() {
this.$data._chart.options = this.options
this.$data._chart.update()
},
deep: true
}
},
mounted() {
this.renderChart(this.chartData, this.options)
}
}
Most helpful comment
Hi @crholliday
Yeah the options are not reactive by default. But like @euledge pointed out, you can simply add a watcher by yourself.
You could try to call
this._chart.update()
which is the internal chart.js method to update the chart instance. However I am not sure if this will work with options.If this is not working, calling
renderChart()
is the right way. But you should destroy the old instance before you do so. BecauserenderChart()
creates a new chartjs instance. Which could lead to weird problems.I will see if I can implement it as a feature :v: so it will work out of the box