I'm trying to create a column chart where the column shows the percentage completed of some task. The data is updated every thirty seconds. I want to make it so that when the job is between 0-50% complete, otherwise, the column is green.
series.columns.template.adapter.add('stroke', (stroke, target) =>
{
let returnValue;
if (target.dummyData.level < 50)
returnValue = "#f26969";
else
returnValue = '#9d4062';
return am4core.color(returnValue);
})
Where level is part of a variable called breakdown assigned to property fields via:
seriesCanisterLevels.tooltip.propertyFields.dummyData = "breakdown";
This code works fine the first time that it is run (ie when the graph is first rendered). If I set the initial value > or < 50, I get the behaviour I expect. However, after that, as the data is dynamically changed every 30 seconds, it does not change the color (though the length of the columns change).
Upon some investigation, it turns out, that a change in a propertyField, and a subsequent chart.invalidateRawData(), does not cause the adapters to fire again. Is there a workaround for this (I do not want to call chart.invalidateData as I don't want to rerender the whole graph, though this does work)
Adapters won't retrigger unless you invalidate the chart and/or associated elements directly (like you noticed) or if the properties assocated with the adapter have been changed. You can mimic the latter by looping through the series columns and assign the stroke to itself after you update the data:
series.columns.each(function(column) {
column.stroke = column.stroke;
})
Demo below:
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [{
"category": "0",
"value": 50,
"breakdown": {
"level": 50
}
}];
// Create axes
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "category";
categoryAxis.renderer.labels.template.disabled = true;
categoryAxis.renderer.grid.template.disabled = true;
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.opposite = true;
valueAxis.renderer.grid.template.disabled = true;
valueAxis.min = 0;
valueAxis.max = 100;
valueAxis.strictMinMax = 0;
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.valueX = "value";
series.dataFields.categoryY = "category";
series.columns.template.tooltipText = "Text: [bold]{dummyData.level}[/]";
series.columns.template.height = am4core.percent(100);
series.columns.template.strokeWidth = 10;
series.sequencedInterpolation = true;
series.columns.template.propertyFields.dummyData = "breakdown";
series.tooltip.propertyFields.dummyData = "breakdown";
series.columns.template.adapter.add('stroke', (stroke, target) => {
let returnValue;
if (target.dummyData.level < 50) {
returnValue = "#f26969";
} else {
returnValue = '#9d4062';
}
return am4core.color(returnValue);
});
setInterval(function() {
var value = Math.floor(Math.random() * 100);
chart.data[0].value = value;
chart.data[0].breakdown.level = value;
chart.invalidateRawData();
series.columns.each(function(column) {
column.stroke = column.stroke;
})
}, 2000)
#chartdiv {
width: 100%;
height: 200px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>