-
Notifications
You must be signed in to change notification settings - Fork 467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Display one label of the sum of stacked bars #16
Comments
Hi @LeoDupont. Can you build a jsfiddle (or similar) with your current chart config and data? It would help to investigate a solution.
|
Hello @simonbrunel, thank you for your answer. I can confirm Regarding Finally, my condition Here is my final snippet, which works as intended: plugins: {
datalabels: {
formatter: (value, ctx) => {
// Array of visible datasets :
let datasets = ctx.chart.data.datasets.filter(
ds => !ds._meta[0].hidden
// ds => ctx.chart.isDatasetVisible(ds.datasetIndex) // <-- does not work
);
// If this is the last visible dataset of the bar :
if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
let sum = 0;
datasets.map(dataset => {
sum += dataset.data[ctx.dataIndex];
});
return sum.toLocaleString(/* ... */);
}
else {
return '';
}
},
anchor: 'end',
align: 'end'
}
} Its JSFiddle : https://jsfiddle.net/78ndvf2n/ I'm concerned about the |
You should really not access _meta directly, that's very internal and have a special structure. If you want to access dataset metadata, you can use |
I think I would move the summation logic into a separated plugin responsible to compute the total for each "stack" and the utmost dataset index, the one for which you want to display the label. It would happen only one time, before the chart update (better for performances): const totalizer = {
id: 'totalizer',
beforeUpdate: chart => {
let totals = {}
let utmost = 0
chart.data.datasets.forEach((dataset, datasetIndex) => {
if (chart.isDatasetVisible(datasetIndex)) {
utmost = datasetIndex
dataset.data.forEach((value, index) => {
totals[index] = (totals[index] || 0) + value
})
}
})
chart.$totalizer = {
totals: totals,
utmost: utmost
}
}
} Then you need to register this plugin to the charts you want to display the total: new Chart('chart', {
plugins: [totalizer],
// ...
} At this point, you can access computed information from new Chart('chart', {
plugins: [totalizer],
options: {
plugins: {
datalabels: {
formatter: (value, ctx) => {
const total = ctx.chart.$totalizer.totals[ctx.dataIndex]
return total.toLocaleString('fr-FR', {
style: 'currency',
currency: 'EUR'
})
},
display: function(ctx) {
return ctx.datasetIndex === ctx.chart.$totalizer.utmost
}
}
}
}
// ...
} Note that it's better to hide the other labels using the Fiddle: https://jsfiddle.net/simonbrunel/9ezggxx5/ This example doesn't take in account all use cases, such as grouped stacks or negative values.
|
I think your solution is much cleaner, so I opted for it. Thank you! PS: I indeed have |
Sounds good! FYI, the
|
Hi. I'm new to using Chart js and I wanted to ask how to put the total count of stacked bar chart at the top of each bar. |
Try this for toggle dataset plugins: { |
I already figured it out but thanks still! |
I know this is an old topic, but I modified Simon's plugin to be usable for grouped stacks. Hope this helps anyone. const totalizer = {
id: 'totalizer',
beforeUpdate: function (chart) {
var totals = [];
var utmost = {};
chart.data.datasets.forEach(function (dataset, datasetIndex) {
if (chart.isDatasetVisible(datasetIndex)) {
var stack = dataset.stack;
utmost[stack] = datasetIndex;
dataset.data.forEach(function (value, index) {
if (totals[index] === undefined) {
totals[index] = {};
}
totals[index][stack] = (totals[index][stack] || 0) + value;
})
}
});
chart.$totalizer = {
totals: totals,
utmost: utmost
}
}
} The totals are then callable by using |
Thanks a lot @michvllni , This helped a lot. Don't forget to use dataIndex and stack as ctx.dataIndex and ctx.stack if u end up in errors. |
I'm trying to add this, but I get this error:
I'm guessing that this is because my |
The provided solutions are for same-length datasets only, right? I'm trying to make it work for that use case but wasn't successful so far. |
I am having the same issue as Synchro- and am also trying to do this in react-chartjs-2. Are there any work-arounds? |
I am just contributing to this incase any one is working with object structured data (
and in the display method:
Hope this helps someone. |
This is great!! thanks a lot. |
Mb a total thread-gravedigger but I've updated this for the version I happened to use, if anybody else is using ChartJS 3.9.x it might help? See https://jsfiddle.net/v3z5umt0/ https://github.com/chartjs/chartjs-plugin-datalabels/issues/91 |
Hi,
I have a horizontal stacked bar chart which looks like this:
And I would like to display the sum of each stacked bar, like so:
I managed to get this result by returning an empty string for datasets that are not the last one (
datasetIndex
), and computing the sum for each bar (dataIndex
):It works great, but if I toggle off one dataset (via the chart's legend), the result is less great:
if I toggle off the first dataset, I still have the sum of the two datasets as a label:
if I toggle off the last dataset, I don't have a label anymore:
As I commented in my code snippet, I tried to filter out the datasets with the
_meta.hidden
metadata, but it seems that theformatter
function is not called again when toggleing datasets via the chart's legend.Is there a better way to use datalabels with stacked bar charts? Or does anyone have an idea to make it work?
The text was updated successfully, but these errors were encountered: