0
votes

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

1

1 Answers

0
votes

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.