I have the following data for different months as bellow
var barChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: 'Task 1',
backgroundColor: "rgba(220,220,220,0.5)",
data: [50, 40, 23, 45, 67, 78, 23]
}, {
label: 'Task 2',
backgroundColor: "rgba(151,187,205,0.5)",
data: [50, 40, 78, 23, 23, 45, 67]
}, {
label: 'Task 3',
backgroundColor: "rgba(82,154,190,0.5)",
data: [50, 67, 78, 23, 40, 23, 0]
}]
};
And I wanted to generate a tooltip like this
I have tried the following code
var ctx = document.getElementById("canvas").getContext("2d");
var myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: true,
text: "Chart.js Bar Chart - Stacked"
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
var tasks = data.datasets[tooltipItem.datasetIndex].label;
var valor = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var count = data.datasets.length;
var total = 0;
var label = '';
for (var i = 0; i < data.datasets.length; i++) {
total += data.datasets[i].data[tooltipItem.index];
}
label += "Total : " + total + "(";
for (var i = 0; i < data.datasets.length; i++) {
label += data.datasets[tooltipItem.datasetIndex].label + " - $" + tooltipItem.yLabel.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ",";
}
var lastChar = label.slice(-1);
if (lastChar === ',') {
label = label.slice(0, -1);
}
label += ")";
return [ label, "Count : " + count ];
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
I need to display a single tooltip per month, so I switch the mode to 'label' and it creates three separate tooltips. How can I achieve the desired output?
Thanks
You were almost there...
The trick is that the callback function must collect and return an array
of labels only once but not for every dataset
.
callbacks: {
label: (tooltipItem, data) => {
if (tooltipItem.datasetIndex > 0) {
return null;
}
There were also issues with accessing wrong objects/properties when composing the main label.
Please have a look at your amended code below.
new Chart("canvas", {
type: 'bar',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: 'Task 1',
backgroundColor: "rgba(220,220,220,0.5)",
data: [50, 40, 23, 45, 67, 78, 23]
}, {
label: 'Task 2',
backgroundColor: "rgba(151,187,205,0.5)",
data: [50, 40, 78, 23, 23, 45, 67]
}, {
label: 'Task 3',
backgroundColor: "rgba(82,154,190,0.5)",
data: [50, 67, 78, 23, 40, 23, 0]
}]
},
options: {
title: {
display: true,
text: "Chart.js Bar Chart - Stacked"
},
tooltips: {
mode: 'label',
callbacks: {
label: (tooltipItem, data) => {
if (tooltipItem.datasetIndex > 0) {
return null;
}
var tasks = data.datasets[tooltipItem.datasetIndex].label;
var valor = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var count = data.datasets.length;
var total = 0;
var label = '';
for (var i = 0; i < data.datasets.length; i++) {
total += data.datasets[i].data[tooltipItem.index];
}
label += "Total : " + total + " (";
for (var i = 0; i < data.datasets.length; i++) {
if (label.endsWith(",")) {
label += " ";
}
label += data.datasets[i].label + " - $" + data.datasets[i].data[tooltipItem.index].toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ",";
}
label = label.slice(0, -1) + ")";
return [label, "Count : " + count];
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="canvas" height="100"></canvas>