Chart.js v2.0: Tooltip only for one dataset - chart.js

I have graph whit this 3 datasets:
this.myChart = new Chart(this.ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [
{ type: 'line', data: data3 },
{ type: 'bar', data: data1, backgroundColor: "#3EAFD5" },
{ type: 'bar', data: data2, backgroundColor: "#D24B47" }
]
}
}
How can I do to show tooltip only for first dataset (type: 'line')?

You can just override the getElementAtEvent method of the chart object
var originalGetElementAtEvent = myChart.getElementAtEvent;
myChart.getElementAtEvent = function () {
return originalGetElementAtEvent.apply(this, arguments).filter(function (e) {
return e._datasetIndex == 0;
});
}
where myChart is your chart object.
Fiddle - http://jsfiddle.net/x4shhvbk/

I make use of the custom tooltip configuration to achieve this:
this.myChart = new Chart(this.ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: "Line 1",
type: 'line',
data: data3
},
{
label: "Bar 1",
type: 'bar',
data: data1,
backgroundColor: "#3EAFD5"
},
{
label: "Bar 2",
type: 'bar',
data: data2,
backgroundColor: "#D24B47"
}
]
},
options: {
responsive: true,
tooltips: {
custom: function(tooltipModel) {
if (tooltipModel.body && tooltipModel.body[0].lines && tooltipModel.body[0].lines[0].indexOf("Bar") > -1) {
tooltipModel.opacity = 0;
}
}
}
}
}

It seems that this funcionality is not added to Chart.js.
I post my solution in this issue: https://github.com/chartjs/Chart.js/issues/1889

Related

Chart js nested pie label colors in legend

I'm trying to have 2 pie charts and show in the legend only the inner labels.
The issues is that seems the labels color (in the legend) are taken from the the outer dataset, probably because it is the first.
How can I change it?
var ctx = $("#myChart");
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['InnerLabel1','InnerLabebl2','InnerLabel3'],
datasets: [{
data: [1, 2, 1, 4],
backgroundColor: [
'rgba(31,119,180,0.5)','rgba(255,127,14,0.5)','rgba(255,127,14,0.5)','rgba(44,160,44,0.5)'
],
labels: [
'OuterLabel1','OuterLabel2','OuterLabel3','OuterLabel4'
]
}, {
data: [1, 3, 4],
backgroundColor: [
'#1f77b4','#ff7f0e','#2ca02c'
],
labels: ['InnerLabel1','InnerLabebl2','InnerLabel3'],
}, ]
},
options: {
responsive: true,
legend: {
display: true,
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ': ' + dataset.data[index];
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
<canvas id="myChart"></canvas>
You probably have to generate the legend labels yourself by defining a legend.labels.generateLabels function together with a legend.onClick that takes care of hiding and showing individual pie slices.
Here's an attempt of how this could be done.
const innerDataset = {
data: [1, 3, 4],
backgroundColor: ['#1f77b4', '#ff7f0e', '#2ca02c'],
labels: ['InnerLabel1', 'InnerLabebl2', 'InnerLabel3'],
};
var myChart = new Chart('myChart', {
type: 'pie',
data: {
datasets: [{
data: [1, 2, 1, 4],
backgroundColor: ['rgba(31,119,180,0.5)', 'rgba(255,127,14,0.5)', 'rgba(255,127,14,0.5)', 'rgba(44,160,44,0.5)'],
labels: ['OuterLabel1', 'OuterLabel2', 'OuterLabel3', 'OuterLabel4']
},
innerDataset
]
},
options: {
responsive: true,
legend: {
display: true,
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ': ' + dataset.data[index];
}
}
},
legend: {
labels: {
generateLabels: () => innerDataset.labels.map((label, i) => ({
text: label,
fillStyle: innerDataset.backgroundColor[i],
strokeStyle: '#fff',
hidden: myChart ? myChart.getDatasetMeta(1).data[i].hidden : false
}))
},
onClick: (event, legendItem) => {
const metaData = myChart.getDatasetMeta(1).data;
const iData = innerDataset.labels.indexOf(legendItem.text);
metaData[iData].hidden = !metaData[iData].hidden;
myChart.update();
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="myChart"></canvas>

Chartjs show hidden data on tooltip

Good Day,
I have a bar chart with multiple datasets for the chart. I would like to hide all the bars except for one (a Totals if you will), and on the Tooltip, I want to show all of the data in all the datasets. Unfortunately, the tooltip only shows the visible datasets. Does anyone know how to show all the data sets?
If you run this with
<canvas id="myChart" width="400" height="400"></canvas>
Hover over the chart and the first dataset (labeled 'First Label') is not shown. How do I show that in the tooltip? Does anyone know?
var ds1 = [], ds2 = [], ds3 = [], ds4 = [], ds5 = [], ds6 = [], labels = [];
for(var i = 0; i < 2; i++){
labels.push('Label: ' + i);
ds1.push(i);
ds2.push(i+1);
ds3.push(i+2);
ds4.push(i+3);
ds5.push(i+4);
ds6.push(i+5);
}
const dataSets = {
labels: labels,
datasets: [
{
label: 'First Label',
hidden: true,
data: ds1
},{
label: 'Second Label',
data: ds2
},{
label: 'Third Label',
data: ds3
},{
label: 'Fourth Label',
data: ds4
},{
label: 'Fifth Label',
data: ds5
},{
label: 'Totals',
data: ds6
}
]
}
var myChart = new Chart(ctx, {
type: 'horizontalBar',
data: dataSets,
elements: {
rectangle: {
borderWidth: 2
}
},
responsive: true,
legend: {
display: false
},
title: {
display: false
},
scales: {
yAxes: [
{
barThickness: 15
}
],
xAxes: [
{
ticks: {
suggestedMin: 0,
suggestedMax: 50
},
minBarLength: 5
}]
}
});
Thanks,
Tim
If you hide all bars except one, you can define a tooltips.callback function for label. This function collects the labels and appropriate values from all datasets using Array.map() and returns a string array.
tooltips: {
callbacks: {
label: (tooltipItem, chart) => dataSets.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index])
}
},
Please have a look at your amended code below:
var ds1 = [], ds2 = [], ds3 = [], ds4 = [], ds5 = [], ds6 = [], labels = [];
for (var i = 0; i < 2; i++) {
labels.push('Label: ' + i);
ds1.push(i);
ds2.push(i + 1);
ds3.push(i + 2);
ds4.push(i + 3);
ds5.push(i + 4);
ds6.push(5 * i + 10);
};
const dataSets = {
labels: labels,
datasets: [{
label: 'First Label',
hidden: true,
data: ds1
}, {
label: 'Second Label',
hidden: true,
data: ds2
}, {
label: 'Third Label',
hidden: true,
data: ds3
}, {
label: 'Fourth Label',
hidden: true,
data: ds4
}, {
label: 'Fifth Label',
hidden: true,
data: ds5
}, {
label: 'Totals',
data: ds6
}]
};
var myChart = new Chart('myChart', {
type: 'horizontalBar',
responsive: true,
data: dataSets,
elements: {
rectangle: {
borderWidth: 2
}
},
options: {
legend: {
display: false
},
title: {
display: false
},
tooltips: {
callbacks: {
label: (tooltipItem, chart) => dataSets.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index])
}
},
scales: {
xAxes: [{
ticks: {
min: 0,
stepSize: 1
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>
If you wanted to display the legend and allow users to show additional bars through a mouse click on individual legend labels, the callback function would be invoked once for each visible bar. Therefore you would have to make sure to return the labels array only once and return null in all other cases. The following code would return the labels array only for the 'Totals' bar.
tooltips: {
callbacks: {
label: (tooltipItem, chart) => {
if (tooltipItem.datasetIndex == dataSets.datasets.length - 1) {
return dataSets.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index]);
}
return null;
}
}
},
This would not work however, if the user decides to hide the 'Totals' bar. The code could however be improved to also overcome this limitation.

ChartJs - Doughnut Chart - how to remove labels if percentage is less than a limit

I am using doughnut from chart.js for visualization in my application.
I need to remove the label if the percentage is bellow a static value like ,20%
This is what i used to generate the labels
var myChartOptions= {
responsive: true,
animation: {
animateScale: true,
animateRotate: true
},
plugins: {
labels: {
render: 'percentage',
fontColor: '#000000',
precision: 2,
}
}
};
I've been working at this for awhile now with no luck.
It looks like chartjs-plugin-labels is being used, in which case passing a custom function to the render option will do the trick, as per the documentation:
const data = [1, 2, 7],
myChartOptions = {
responsive: true,
animation: {
animateScale: true,
animateRotate: true
},
plugins: {
labels: {
render: args => {
if (args.percentage < 20) {
return '';
}
return args.percentage + '%';
},
fontColor: '#000000',
precision: 2,
}
}
};
new Chart(document.getElementById('myChart'), {
type: 'doughnut',
data: {
datasets: [{
label: 'series 1',
data: data,
backgroundColor: ['pink', 'lightgreen', 'lightblue'],
}]
},
options: myChartOptions
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/emn178/chartjs-plugin-labels/src/chartjs-plugin-labels.js"></script>
<canvas id="myChart"></canvas>

Chart.js 2 line charts with separate dataset labels

I need build 2 lines charts with different sets of labels
here is example https://jsfiddle.net/o5dtzwn1/
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data: [1, 2, 3, 4, 5],
labels: [
'green',
'yellow',
'red',
'purple',
'blue',
]
}, {
data: [6, 7, 8],
labels: [
'a',
'b',
'c'
],
}, ]
},
options: {
responsive: true,
legend: {
display: false,
},
}
});
How can I do this?
Ok, that could help you, Now I have made different line chart with four different data with different counts.
Here i have made three label array and attached to tick callback function randomly.
You can choose whichever apropriate, but make sure bigger atrray lenth should come
in to data: { labels: label1}.
Check link enter link description here
var ctx = document.getElementById("myChart");
var label1 = ["aa", "bb", "cc", "dd", "ee", "ff", "gg"];
var label2 = ["1900", "1950", "1999", "2050"];
var label3 = ["AA", "BB", "CC", "DD", "EE"];
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: label1,
datasets: [{
label: "Europe",
type: "line",
borderColor: "#8e5ea2",
data: [408, 547, 675, 934],
fill: false
}, {
label: "Africa",
type: "line",
borderColor: "magenta",
data: [133, 221, 783, 2478, 1900, 1200],
fill: false
}, {
label: "Europe",
type: "line",
borderColor: "green",
data: [408, 547, 675, 734, 200],
fill: false
}, {
label: "Africa",
type: "line",
borderColor: "red",
//backgroundColorHover: "#3e95cd",
data: [133, 221, 783, 2478],
fill: false
}]
},
options: {
title: {
display: true,
text: 'Population growth (millions): Europe & Africa'
},
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
// Include a dollar sign in the ticks
callback: function(value, index, values) {
if (label3[index] === undefined) {
label3[index] = "no data ";
}
if (label2[index] === undefined) {
label2[index] = "no data ";
}
return "l3 " + label3[index] + "l2 " + label2[index] + ' $' + value;
}
}
}]
}
}
});
//use following code that might helpful
var ctx = $("#myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [1500,1600,1700,1750,1800,1850,1900,1950,1999,2050],
datasets: [{
data: [86,114,106,106,107,111,133,221,783,2478],
label: "Africa",
borderColor: "#3e95cd",
fill: false
}, {
data: [282,350,411,502,635,809,947,1402,3700,5267],
label: "Asia",
borderColor: "#8e5ea2",
fill: false
}, {
data: [168,170,178,190,203,276,408,547,675,734],
label: "Europe",
borderColor: "#3cba9f",
fill: false
}, {
data: [40,20,10,16,24,38,74,167,508,784],
label: "Latin America",
borderColor: "#e8c3b9",
fill: false
}, {
data: [6,3,2,2,7,26,82,172,312,433],
label: "North America",
borderColor: "#c45850",
fill: false
}
]
},
options: {
title: {
display: true,
text: 'World population per region (in millions)'
}
}
});
I think this one as you mention have different label and differnt data and count
// here is link https://codepen.io/hiren65/pen/ydMZaJ
var ctx = $("#myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data: [1, 2, 6, 11, 5],
type: "line",
borderColor: "red",
labels: [
'green',
'yellow',
'red',
'purple',
'blue',
]
}, {
data: [6, 7, 8],
type: "line",
borderColor: "#123ea2",
labels: [
'a',
'b',
'c'
],
}, {
data: [6, 3, 8,10,11,4],
type: "line",
borderColor: "#6cc",
labels: [
'a1',
'b1',
'c1',
'e1'
],
},]
},
options: {
responsive: true,
legend: {
display: true,
},
}
});

How to show different product name for every bar in chart js

I am using chart js for showing top 3 sold products in last week.
I want to show product name in tooltip for every bar which has obviously different products.
Here is my code :
function productChart() {
var data = {
labels: productHistoryDates,
datasets: [{
label: 'Product 1',
data: productHistoryProducts1,
backgroundColor: "#26B99A"
},
{
label: 'Product 2',
data: productHistoryProducts2,
backgroundColor: "#03586A",
},
{
label: 'Product 3',
data: productHistoryProducts3,
backgroundColor: "#03226A",
}]
};
var ctx = document.getElementById("productChart").getContext("2d");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
tooltips: {
enabled: true,
mode: 'single',
},
scales: {
yAxes: [{
gridLines: {
display: true
}
}],
xAxes: [{
gridLines: {
display: true
},
barPercentage: 0.8
}]
}
}
});
}
I am getting output like this.
But instead of product 1 label I want product name for that particular bar how can I achieve that ?
I solved it.
by passing an array to the label in data. And rest of the code is as below.
function productChart() {
var data = {
labels: productHistoryDates,
datasets: [{
label: productHistoryProducts1.name,
data: productHistoryProducts1.quantity,
backgroundColor: "#26B99A"
},
{
label: productHistoryProducts2.name,
data: productHistoryProducts2.quantity,
backgroundColor: "#03586A",
},
{
label: productHistoryProducts3.name,
data: productHistoryProducts3.quantity,
backgroundColor: "#03226A",
}]
};
var ctx = document.getElementById("productChart").getContext("2d");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
tooltips: {
enabled: true,
mode: 'single',
callbacks: {
label: function (tooltipItems, data) {
var tooltip = data.datasets[tooltipItems.datasetIndex].label[tooltipItems.index];
return tooltip;
}
}
},
scales: {
yAxes: [{
gridLines: {
display: true
}
}],
xAxes: [{
gridLines: {
display: true
},
ticks: { mirror: true },
barPercentage: 0.8
}]
}
}
});
}