Reputation: 6276
I'm trying to build a component for am4chart
in vuejs
which I can re-utilise at different places, I've a some search options which changes the chartData
values as per the search result.
When my search page loads, it displays the chart perfectly but when I try to check filters it doesn't change or show as per the data. I have all the code related to am4Chart
in mounted
section, so I tried placing the same in my methods
and tried calling the method
in mounted section from there. I also put a watch
function so that the function can be called again when the data changes. But when I place it in methods
the whole chart
vanishes, in-fact if I place the same code in mounted
and methods
section it doesn't display.
I've checked via console my method
is being called when chartData
changes but don't know how can I make it reactive.
VueJS
version 2.6.10
am4Chart
version 4.4.10
My code:
<template>
<div ref="amchart_semi_pie_chart"></div>
</template>
<script>
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
export default {
name: "amchart-semi-pie-chart",
props: {
chartData: Object,
},
data() {
return {
chart: '',
}
},
methods: {
loadChart() {
console.log('Values are changed')
}
},
mounted() {
//Creating charts
let chart = am4core.create(this.$refs.amchart_semi_pie_chart, am4charts.PieChart);
chart.hiddenState.properties.opacity = 0; // this creates initial fade-in
chart.data = this.chartData.data;
// Add and configure Series
chart.radius = am4core.percent(70);
chart.innerRadius = am4core.percent(40);
chart.startAngle = 180;
chart.endAngle = 360;
let series = chart.series.push(new am4charts.PieSeries());
series.dataFields.value = "value";
series.dataFields.category = "label";
series.slices.template.cornerRadius = 10;
series.slices.template.innerCornerRadius = 7;
series.slices.template.draggable = true;
series.slices.template.inert = true;
series.alignLabels = false;
if(this.chartData.legends)
chart.legend = new am4charts.Legend();
this.chart = chart;
},
watch: {
chartData: {
handler: 'loadChart',
deep: true
}
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
}
}
}
</script>
Upvotes: 1
Views: 3562
Reputation: 21
Had the same problem and after some digging I found you can refresh the data using chart.invalidateRawData().
See documentation AMCharts Data - Dynamic Updates (Manipulating existing data points)
I applied this on the watch method of the prop which worked for me....
<template>
<div ref="amchart_semi_pie_chart"></div>
</template>
<script>
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
export default {
name: "amchart-semi-pie-chart",
props: {
chartData: Object,
},
data() {
return {
chart: '',
}
},
methods: {
loadChart() {
console.log('Values are changed')
this.chart.invalidateRawData();
}
},
mounted() {
//Creating charts
let chart = am4core.create(this.$refs.amchart_semi_pie_chart, am4charts.PieChart);
chart.hiddenState.properties.opacity = 0; // this creates initial fade-in
chart.data = this.chartData.data;
// Add and configure Series
chart.radius = am4core.percent(70);
chart.innerRadius = am4core.percent(40);
chart.startAngle = 180;
chart.endAngle = 360;
let series = chart.series.push(new am4charts.PieSeries());
series.dataFields.value = "value";
series.dataFields.category = "label";
series.slices.template.cornerRadius = 10;
series.slices.template.innerCornerRadius = 7;
series.slices.template.draggable = true;
series.slices.template.inert = true;
series.alignLabels = false;
if(this.chartData.legends)
chart.legend = new am4charts.Legend();
this.chart = chart;
},
watch: {
chartData: {
handler: 'loadChart',
deep: true
}
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
}
}
}
</script>
Upvotes: 2
Reputation: 78
I know this is old and you might have moved on with the project but since today I faced the same issue and found a solution, I thought it would be nice to reply. In my case, instead of using props I was using computed properties for the data set. I've tried a few things and the one that did the trick for me was to wrap the entire chart creation into a method and watch that computed property (in your case the prop) for changes and fire up the method again. It is visible that the chart is really re-drawn which is not as nice as only having the animation of the changes but for now, it works fine.
So, your code would look something like this:
<template>
<div ref="amchart_semi_pie_chart"></div>
</template>
<script>
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
export default {
name: "amchart-semi-pie-chart",
props: {
chartData: Object,
},
data() {
return {
chart: '',
}
},
methods: {
loadChart() {
console.log('Values are changed')
},
renderChart() {
//Creating charts
let chart = am4core.create(this.$refs.amchart_semi_pie_chart, am4charts.PieChart);
chart.hiddenState.properties.opacity = 0; // this creates initial fade-in
chart.data = this.chartData.data;
// Add and configure Series
chart.radius = am4core.percent(70);
chart.innerRadius = am4core.percent(40);
chart.startAngle = 180;
chart.endAngle = 360;
let series = chart.series.push(new am4charts.PieSeries());
series.dataFields.value = "value";
series.dataFields.category = "label";
series.slices.template.cornerRadius = 10;
series.slices.template.innerCornerRadius = 7;
series.slices.template.draggable = true;
series.slices.template.inert = true;
series.alignLabels = false;
if(this.chartData.legends)
chart.legend = new am4charts.Legend();
this.chart = chart;
}
},
mounted() {
renderChart();
},
watch: {
chartData: {
renderChart();
}
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
}
}
}
</script>
Upvotes: 1