Chart.js v3: Tooltip callback doesn't identify clicked dataset of stacked bar chart - javascript

In Chart.js v2, the datasetIndex property of ChartTooltipItem[] identifies which segment of a stacked bar chart was clicked. This allowed the tooltip content to be customized for each segment of the stacked bar chart.
In v3, TooltipItem[] provides the datasets but does not identify which one was clicked. There is a datasetIndex field for each TooltipItem, but it just matches the index in TooltipItem[] rather than identify the clicked segment.
Has anyone found a field in the V3 tooltip callback to identified which segment of a stacked bar chart was clicked? Or was this functionality lost in the v3 rewrite?

It just works fine, the only thing that is different is that it seems like in v2 it defaulted to the point mode while now it is using index mode, if you change it back to point it works as expected:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'red'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: 'blue'
}
]
},
options: {
plugins: {
tooltip: {
mode: 'point',
callbacks: {
beforeBody: (ttItems, x) => {
ttItems.forEach((ttItem) => {
console.log('BeforeBody: ', ttItem.datasetIndex, ttItem.dataIndex)
})
},
afterBody: (ttItems, x) => {
ttItems.forEach((ttItem) => {
console.log('AfterBody: ', ttItem.datasetIndex, ttItem.dataIndex)
})
}
}
}
},
scales: {
y: {
stacked: true
},
x: {
stacked: true
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.1/chart.js"></script>
</body>

Related

React-Chart.js legend onClick function

I'm working on a bar chart with multiple stacked datasets using the react wrapper for Chart.js(https://github.com/reactchartjs/react-chartjs-2).
I've been trying to make the chart show only one dataset at a time, but I'm having trouble coming up with the right function.
I want the chart to start off with all the datasets hidden(this part was easy) and when you click the legend I want the chart to only show only the selected dataset. So when you click one and then another I want the first one to get hidden.
I know I need to use the legend onClick option but I can't figure out how to set it up.
Any help would be appreciated, thanks!
Edit: Here is the chart in question: https://codesandbox.io/s/lucid-river-xhvtd?file=/src/charts/bar_chart.js
You can set all datasets to hide and then only the one clicked to show:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink',
hidden: true
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange',
hidden: true
},
{
label: '# of People',
data: [3, 1, 15, 4, 9, 12],
borderColor: 'cyan',
hidden: true
}
]
},
options: {
plugins: {
legend: {
onClick: (evt, legendItem, legend) => {
const index = legendItem.datasetIndex;
const ci = legend.chart;
legend.chart.data.datasets.forEach((d, i) => {
ci.hide(i);
d.hidden = true;
})
ci.show(index);
legendItem.hidden = false;
ci.update();
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>

ChartJS - Moving vertical line is display on top of tooltip

Hello,
I've followed this post (Moving vertical line when hovering over the chart using chart.js) to draw a vertical line on my chart.
With a single dataset, it's working just fine.
But for a multiple datasets display (with stacked options on the y-axis), the vertical line is drawn over the chart's tooltip.
Neither setting the z-index of the chart's tooltip nor the vertical line could solve my problem. Since I can't find any property to do that.
Do you have any idea/suggestion to solve this issue?
I'm using react-chart-js 2 with chart-js ^2.9.4 as a peer dependency.
You can use a custom plugin that draws after all the datasets have drawn but before the tooltip is drawn:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
stacked: true
}]
},
plugins: {
customLine: {
width: 5,
color: 'pink'
}
}
},
plugins: [{
id: 'customLine',
afterDatasetsDraw: (chart, x, opts) => {
const width = opts.width || 1;
const color = opts.color || 'black'
if (!chart.active || chart.active.length === 0) {
return;
}
const {
chartArea: {
top,
bottom
}
} = chart;
const xValue = chart.active[0]._model.x
ctx.lineWidth = width;
ctx.strokeStyle = color;
ctx.beginPath();
ctx.moveTo(xValue, top);
ctx.lineTo(xValue, bottom);
ctx.stroke();
}
}]
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</body>

how to display last x float number value in chartjs

I'm making a Vertical Bar Chart using react-chartjs-2.
and I have array of lots of float numbers stored.
I tried to use chartjs callback option to display only the last value on a graph.
But the value in the callback is an integer, so I can't take the value I want.
for example,
const xAsisData = [ 1.11, 4.23, 7.34, ... , 403.78 ] // includes hundreds
scales: {
x: {
ticks: {
autoSkip: false,
callback: (value) => {
// if value === last ? value : null
// ! but last value is 309, not 403.78
},
},
Is there any other option I can use?
You get the index and ticks array as well in your callback so you can just check if the index is not the final one like so:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
y: {
ticks: {
callback: (val, i, ticks) => (i < ticks.length - 1 ? val : null) // Replace null by empty string to still show the gridLine
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.js"></script>
</body>

How do I remove cartesian axes from chart js?

I am trying to personalize a chart.js. But I can not find how to remove (or hide) the X and Y axes.
I am also interested in not showing data on hover and I would like not to show the reference on the top. I am just starting with chart.js and I only need to do a few graphs.
Thank you :)
This is the graph I currently have
datasets: {
label: "I need help plz",
backgroundColor: gradient,
fill: true,
borderColor: "rgb(0, 50, 100)",
borderWidth: 0.001,
tension: 0.4,
radius: 0,
data: dataset,
},
For removing the references on the top this post was useful Chart.js v2 hide dataset labels
As described in the documentation (https://www.chartjs.org/docs/master/axes/#common-options-to-all-axes) you can set in the options of the scale the display to true or false or 'auto' where auto hides the scale if no dataset is visable that is linked to that axis.
For not showing data on hover you can set the tooltip to enabled: false
Example (y auto display and no x axis):
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1,
backgroundColor: 'red'
}, ]
},
options: {
plugins: {
tooltip: {
enabled: false
}
},
scales: {
y: {
display: 'auto'
},
x: {
display: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.js"></script>
</body>

Show data values in Chart.js bars (version 3)

There is a thread with many answers on this topic (Show values on top of bars in chart.js), but it's all about version 2.x
getDatasetMeta() has been deprecated:
https://www.chartjs.org/docs/3.0.2/getting-started/v3-migration.html
The "datalabels" plugin has not been ported to 3.x:
https://github.com/chartjs/chartjs-plugin-datalabels
Have you found any working solutions? How can data values be displayed on top of vertical barcharts (or next to horizontal barcharts)?
You can use the beta of the datalabels plugin.
Documentation: https://v2_0_0-rc_1--chartjs-plugin-datalabels.netlify.app/
Script tag: <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0-rc/dist/chartjs-plugin-datalabels.min.js"></script>
Install command: npm i chartjs-plugin-datalabels#next
Live example:
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.3.0/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0-rc"></script>
<canvas id="myChart" width="850" height="520"></canvas>
<script>
var ctx = document.getElementById('myChart');
Chart.register(ChartDataLabels); // first way of registering the plugin, registers them for all your charts
var myChart = new Chart(ctx, {
type: 'bar',
plugins: [ChartDataLabels], // second way of registering plugin, register plugin for only this chart
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
data: [12, 19, 3, 5, 2, 3],
label: 'Advisor Closed MTD',
backgroundColor: 'rgb(192,111,94)',
barThickness: 25,
datalabels: {
color: '#FFCE56'
}
}],
},
options: {
responsive: false,
plugins: {
datalabels: {
anchor: 'end', // remove this line to get label in middle of the bar
align: 'end',
formatter: (val) => (`${val}%`),
labels: {
value: {
color: 'blue'
}
}
}
}
}
});
</script>

Categories