On a horizontal bar chart, being fed from an external data source, I need to change the data values to text (for display purposes) on the valueAxis labels and tooltip text.
I've managed to find a way to change the valueAxis labels, which seems to work (although not sure if it's best practice?).
But I'm struggling to change the text on the valueAxis tooltip and series tooltip, as shown in the screenshot, where "3" needs to display as "FAIRLY IMPORTANT" as well as the other values when hovering over the chart.
EDIT
I've added this code which calls the amCharts adapter, and returns the valueAxis text as XXXXXX, but the target values are not working as they should.
I can't see where I'm going wrong though?
// This Adapter is to change the text in the valueAxis Tooltip
valueAxis.adapter.add("getTooltipText", (text, target) => {
if (target.dataItem && (target.dataItem.value == 0)) {
return "NOT NEEDED";
}
if (target.dataItem && (target.dataItem.value == 1)) {
return "UNSURE";
}
if (target.dataItem && (target.dataItem.value == 3)) {
return "NICE TO HAVE";
}
if (target.dataItem && (target.dataItem.value == 5)) {
return "MUST HAVE";
}
else {
return "XXXXXX";
}
});
Quick summary below.
The data source comes in as...
"Name": "Photographer",
"Category A": 3,
"Category B": 5,
"Category C": 1,
"Category D": 0,
"Category E": 3
On the chart, I want to display the numeric values as text...
0 to display as FAIRLY IMPORTANT
1 to display as NOT SURE
3 to display as FAIRLY IMPORTANT
5 to display as VERY IMPORTANT
Here's my code (so far) which I need to clean up a bit once I've finished working on it...
// Create chart instance
var chart = am4core.create("CHARTDIV", am4charts.XYChart);
// base64 encoded version of sample data as a data URI
function dataURI() {
return "data:application/json;base64,ewogICJyZWNvcmRzIjogWwogICAgewogICAgICAiaWQiOiAxLAogICAgICAiZmllbGRzIjogewogICAgICAgICJOYW1lIjogIlBob3RvZ3JhcGhlciIsCiAgICAgICAgIkNhdGVnb3J5IEEiOiAzLAogICAgICAgICJDYXRlZ29yeSBCIjogNSwKICAgICAgICAiQ2F0ZWdvcnkgQyI6IDEsCiAgICAgICAgIkNhdGVnb3J5IEQiOiAwLAogICAgICAgICJDYXRlZ29yeSBFIjogMwogICAgICB9LAogICAgICAiY3JlYXRlZFRpbWUiOiAiMjAxOC0wNC0xMlQxNzoyNzowNi4wMDBaIgogICAgfQogIF0KfQ==";
}
// Add data
chart.dataSource.url = dataURI(); //fake URL for demonstration purposes
// Always needed when using Airtable JSON output for amCharts compatibility
chart.dataSource.events.on("parseended", function(ev) {
// parsed data is assigned to data source's `data` property
ev.target.data = ev.target.data.records.map(function(dataItem) {
return {
"Category A": dataItem.fields["Category A"],
"Category B": dataItem.fields["Category B"],
"Category C": dataItem.fields["Category C"],
"Category D": dataItem.fields["Category D"],
"Category E": dataItem.fields["Category E"],
"Name": dataItem.fields.Name
}
});
});
// Needed when the Airtable rows and columns need transposing
chart.dataSource.events.on("parseended", function(ev) {
var questionMap = {}; //lookup table to map questions to data elements
ev.target.data.forEach(function(item) {
Object.keys(item).forEach(function(key) {
if (key.indexOf('Name') == -1) { //act on non-response keys
if (!questionMap[key]) {
questionMap[key] = {
"Name": key
}; //create an object containing the name/question pair if it doesn't exist
}
questionMap[key][item.Name] = item[key]; // assign response+value to the object (e.g. "Must Have": 75)
}
});
});
//remap lookup table as array
ev.target.data = Object.keys(questionMap).map(function(question) {
return questionMap[question];
});
});
// Set cell size in pixels
var cellSize = 50;
chart.events.on("datavalidated", function(ev) {
// Get objects of interest
var chart = ev.target;
var categoryAxis = chart.yAxes.getIndex(0);
// Calculate how we need to adjust chart height
var adjustHeight = chart.data.length * cellSize - categoryAxis.pixelHeight;
// get current chart height
var targetHeight = chart.pixelHeight + adjustHeight;
// Set it on chart's container
chart.svgContainer.htmlElement.style.height = targetHeight + "px";
});
// Create category axes
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "Name";
categoryAxis.renderer.grid.template.location = 0;
// Bar or column width for category axis
categoryAxis.renderer.cellStartLocation = 0.1;
categoryAxis.renderer.cellEndLocation = 0.9;
// Create value axes
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.numberFormatter.numberFormat = "#";
valueAxis.min = 0;
valueAxis.max = 6;
valueAxis.cursorTooltipEnabled = true;
// Create value axes - LABELS DISABLED
valueAxis.renderer.grid.template.disabled = true;
valueAxis.renderer.labels.template.disabled = true;
// Create value axes - DEFINE GRID LINES
function createGrid(value) {
var range = valueAxis.axisRanges.create();
range.value = value;
range.label.text = "";
}
createGrid(0);
createGrid(1);
createGrid(3);
createGrid(5);
createGrid(6);
// Create value axes - DEFINE GRID LABELS
function createLabel(value, label, location) {
var range = valueAxis.axisRanges.create();
range.value = value;
range.grid.strokeOpacity = 0;
range.label.location = location | 0;
range.label.dataItem.text = label;
range.label.fillOpacity = 1;
}
createLabel("0", "NOT IMPORTANT");
createLabel("1", "NOT SURE");
createLabel("3", "FAIRLY IMPORTANT");
createLabel("5", "VERY IMPORTANT");
// This Adapter is to change the text in the valueAxis Tooltip
valueAxis.adapter.add("getTooltipText", (text, target) => {
if (target.dataItem && (target.dataItem.value >= 0)) {
return "NOT IMPORTANT";
}
if (target.dataItem && (target.dataItem.value == 1)) {
return "NOT SURE";
}
if (target.dataItem && (target.dataItem.value == 3)) {
return "FAIRLY IMPORTANT";
}
if (target.dataItem && (target.dataItem.value == 5)) {
return "VERY IMPORTANT";
}
else {
return "XXXXXX";
}
});
// Create series
function createSeries(field, name) {
// Set up series
var series = chart.series.push(new am4charts.ColumnSeries());
series.name = name;
series.dataFields.valueX = field;
series.dataFields.categoryY = "Name";
series.sequencedInterpolation = true;
// Make it stacked
series.stacked = true;
// Configure columns
series.tooltip.getFillFromObject = false;
series.tooltip.background.fill = am4core.color("#272d3a");
series.tooltip.background.strokeWidth = 0;
series.tooltipText = "{name}: [bold]{valueX}[/]";
series.tooltip.paddingTop = -1;
series.tooltip.fontSize = 16;
// Add label
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color("#fff");
bullet.circle.strokeWidth = 2;
return series;
}
var series1 = createSeries("Photographer", "Photographer");
// Labels configuration for category axis
var categoryLabel = categoryAxis.renderer.labels.template;
categoryLabel.fill = am4core.color("#272d3a");
categoryLabel.fontSize = 16;
categoryLabel.fontWeight = 700;
categoryLabel.truncate = true;
// Labels configuration for value axis
var valueLabel = valueAxis.renderer.labels.template;
valueLabel.fill = am4core.color("#272d3a");
valueLabel.fontSize = 16;
// Tooltip configuration for category axis
var categoryTooltip = categoryAxis.tooltip;
categoryTooltip.background.fill = am4core.color("#272d3a");
categoryTooltip.fontSize = 16;
categoryTooltip.fontWeight = 700;
categoryTooltip.background.strokeWidth = 0;
categoryTooltip.background.cornerRadius = 3;
categoryTooltip.background.pointerLength = 4;
categoryTooltip.dy = 0;
categoryTooltip.dx = -2;
categoryTooltip.paddingTop = 0;
// Tooltip configuration for value axis
var valueTooltip = valueAxis.tooltip;
valueTooltip.background.fill = am4core.color("#272d3a");
valueTooltip.fontSize = 16;
valueTooltip.background.strokeWidth = 0;
valueTooltip.background.cornerRadius = 3;
valueTooltip.background.pointerLength = 4;
valueTooltip.dy = 2;
valueTooltip.dx = 0;
valueTooltip.paddingTop = 0;
// Tooltip configuration for value axis - DISABLED
valueTooltip.disabled = false;
// Add cursor
chart.cursor = new am4charts.XYCursor();
chart.cursor.behavior = "zoomXY";
chart.cursor.lineX.disabled = true;
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<div id="CHARTDIV" style="width: 100%; height: 600px;"></div>
