Chartjs v2 - format tooltip for multiple data sets (bar and line)

Viewed 23308

Reading up a lot on how to format the tooltip in ChartJS v2.x utilizing the tooltip callback. I've had success thus far, but find that I'm unable to define two separate formats for the two data sets I have.

As a bit more context, I have a line chart overlayed on top of a bar chart:

  • My bar data is numerical (in the millions, and needs to be rounded and truncated).
  • Example: 22345343 needs to be shown as 22M in the tooltip

  • My line data is a currency
  • Example: 146.36534 needs to shown as $146.37 in the tooptip

Here's my short WIP code thus far. This formats the tooltip to round and include the $ sign. How can I expand this so that I can separately format my bar data correctly in the tooltip?


tooltips: {
                mode: 'index',
                intersect: false,
                callbacks: {
                    label: function(tooltipItem, data) {
                        return "$" + Number(tooltipItem.yLabel).toFixed(2).replace(/./g, function(c, i, a) {
                                    return i > 0 && c !== "." && (a.length - i) % 3 === 0 ? "," + c : c;
                                });
                    }
                }
            }
3 Answers

Try using below code!

   let  DoughnutForSavingCount = {
        labels: [
          intl.formatMessage({ id: 'Guarantee' }),
          intl.formatMessage({ id: 'ILAS' }),
          intl.formatMessage({ id: 'No Idea' })
        ],

        datasets: [
          /* Outer doughnut data starts*/

          {
            label: 'Graph1',
            data: [
              _.get(getClientSavingILASPolicyData[0], 'countwithGuaranttee') >
                0 &&
              _.get(getClientSavingILASPolicyData[0], 'totalWithGuarantee') ===
                0
                ? 0.1
                : _.get(getClientSavingILASPolicyData[0], 'totalWithGuarantee'),
              _.get(getClientSavingILASPolicyData[0], 'countwithILAS', 0) > 0 &&
              _.get(getClientSavingILASPolicyData[0], 'totalWithILAS') === 0
                ? 0.1
                : _.get(getClientSavingILASPolicyData[0], 'totalWithILAS'),
              _.get(getClientSavingILASPolicyData[0], 'countNoIdea', 0) > 0 &&
              _.get(getClientSavingILASPolicyData[0], 'totalWithNoIdea') === 0
                ? 0.1
                : _.get(getClientSavingILASPolicyData[0], 'totalWithNoIdea')
            ],
            backgroundColor: ['#8c1aff', '#BF80FF', '#E9e9e9'],
            hoverBackgroundColor: ['#8c1aff', '#BF80FF', '#E9e9e9']
          },
          /* Outer doughnut data ends*/

          /* Inner doughnut data starts*/
          {
            label: 'Graph2',
            data: [
              _.get(getClientSavingILASPolicyData[0], 'countwithGuaranttee'),
              _.get(getClientSavingILASPolicyData[0], 'countwithILAS'),
              _.get(getClientSavingILASPolicyData[0], 'countNoIdea')
            ],
            backgroundColor: ['#8c1aff', '#BF80FF', '#E9e9e9'],
            hoverBackgroundColor: ['#8c1aff', '#BF80FF', '#E9e9e9']
          }
          /* Inner doughnut data ends*/
        ],
        borderWidth: [1]
      };



     let DoughnutForSavingCountConfig = {
          cutoutPercentage: 70,
          legend: {
            display: true,
            position: 'bottom',
            labels: {
              fontColor: '#34A0DC',
              fontSize: 10,
              fontFamily: 'Helvetica',
              boxWidth: 10,
              usePointStyle: true
            }
          },
          responsive: true,
          plugins: {
            datalabels: {
              display: false
            }
          },
          tooltips: {
            enabled: true,
            //*****add for reference********** */
            callbacks: {
              label: function(tooltipItems, data) {
                if (tooltipItems.datasetIndex) {
                  var label = data.labels[tooltipItems.index] || '';
                  var currentValue =
                    data.datasets[tooltipItems.datasetIndex].data[
                      tooltipItems.index
                    ];
                  if (label) {
                    label += ': ';
                  }
                  label += currentValue == '0.1' ? '0' : currentValue;
                  return label;
                } else {
                  var label = data.labels[tooltipItems.index] || '';
                  var currentValue =
                    data.datasets[tooltipItems.datasetIndex].data[
                      tooltipItems.index
                    ];
                  if (label) {
                    label += ': ';
                  }
                  label += intl.formatMessage({ id: 'HKD' }) + ' ';
                  label +=
                    currentValue == '0.1'
                      ? '0'
                      : currentValue
                          .toString()
                          .replace(/\B(?=(\d{3})+(?!\d))/g, ',');
                  return label;
                }
              }
            }
          }
        };

Thanks, GRUNT! But since my datasets could me mixed it's better to use the yAxisID to check for the correct dataset.

            tooltips: {
                callbacks: {
                    label: function (tooltipItem, details) {
                        if (details.datasets[tooltipItem.datasetIndex].yAxisID == "$") {
                            let dataset = details.datasets[tooltipItem.datasetIndex];
                            let currentValue = dataset.data[tooltipItem.index];
                            return dataset.label + ": " + currentValue.toFixed(2) + " $";
                        } else {
                            let dataset = details.datasets[tooltipItem.datasetIndex];
                            let currentValue = dataset.data[tooltipItem.index];
                            return dataset.label + ": " + currentValue +" pieces";
                        }
                    }
                }
            }
Related