Krono
Krono

Reputation: 1362

ChartJS Tooltip Customization

I'm running ChartJS 2.7.something, and have https://codepen.io/anon/pen/YBJWKX this graph. Code below:

var ctx = document.getElementById("chart");

Chart.controllers.LineWithLine = Chart.controllers.line.extend({
draw: function(ease) { Chart.controllers.line.prototype.draw.call(this, ease);

if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
  let activePoint = this.chart.tooltip._active[0],
    ctx = this.chart.ctx,
    x = activePoint.tooltipPosition().x,
    topY = this.chart.scales['y-axis-a'].top,
    bottomY = this.chart.scales['y-axis-a'].bottom;

  // draw line
  ctx.save();
  ctx.beginPath();
  ctx.moveTo(x, topY);
  ctx.lineTo(x, bottomY);
  ctx.lineWidth = 1;
  ctx.strokeStyle = 'rgba(52,58,64,1)';
  ctx.stroke();
  ctx.restore();
  }
 }
});

var dashboard = new Chart(ctx, {
type: 'bar',
data: {
    responsive: true,
    labels: ["1", "2", "3", "4", "5", "6", "7"],
    datasets: [{
      label: 'No Data',
      yAxisID: 'y-axis-a',
      data: [null,null,4000, null, null, 4000, null],
      backgroundColor: 'rgba(229,229,229,1)',
      borderWidth: '0',
      borderSkipped: 'bottom',
      hoverBackgroundColor: 'rgba(229,229,229,1)',
      hoverBorderWidth: '0',
      showTooltip: false,
    },
    {
        type: 'LineWithLine',
        label: 'Dummy 1',
        fill: false,
        yAxisID: 'y-axis-a',
        data: [2586, 2343, 2380, 2439, 3316, 1570, 3439],
        borderColor: 'rgba(220,53,69,1)',
        backgroundColor: 'rgba(220,53,69,1)',
        borderWidth: 3,
        borderCapStyle: 'butt',
        pointRadius: 2,
        pointBorderWidth: 0,
        pointHoverRadius: 1,
        pointHitRadius: 10,
        lineTension: 0.1, // Removes Bezier on Line
    },
    {
      type: 'LineWithLine',
      label: 'Dummy 2',
      fill: false,
      yAxisID: 'y-axis-a',
      data: [3466, 1295, 3015, 2351, 3305, 1167, 1350],
      borderColor: 'rgba(40, 167, 69,1)',
      backgroundColor: 'rgba(40, 167, 69,1)',
      borderWidth: 3,
      borderCapStyle: 'butt',
      pointRadius: 2,
      pointBorderWidth: 0,
      pointHoverRadius: 1,
      pointHitRadius: 10,
      lineTension: 0.1, // Removes Bezier on Line
    },
    {
      type: 'LineWithLine',
      label: 'Dummy 3',
      fill: false,
      yAxisID: 'y-axis-b',
      data: [1, 8, 17, 6, 12, 4, 7],
      borderColor: 'rgba(0, 123, 255,1)',
      backgroundColor: 'rgba(0, 123, 255,1)',
      borderWidth: 3,
      borderCapStyle: 'butt',
      pointRadius: 2,
      pointBorderWidth: 0,
      pointHoverRadius: 1,
      pointHitRadius: 10,
      lineTension: 0.1, // Removes Bezier on Line
    },
  ]
},
options: {
    bezierCurve: false,
    maintainAspectRatio:false,
    legend: {
      labels: {
        filter: function(item, dashboard) {
           // Logic to remove a particular legend item goes here
           return !item.text.includes('No Data');
        }
      }
    },
    tooltips: {
      mode: 'index',
      intersect: false,
      //enabled: false,
    },
    scales: {
      yAxes: [{
          position: "left",
          id: "y-axis-a",
          ticks: {
            suggestedMax: 3600,
          }
        },
        {
            position: "left",
            id: "y-axis-b",
            max: 25,
            display: false,
            gridLines: {
                display:false
            }
            }],
        },
      xAxes: [{ }]
    }
});

It's almost perfect for what i need it for, however:

In this particular case I would like to remove the "No Data" grey bars from the tooltip where it's values are NULL.

At the same time, i would also like to remove the tooltip entirely where it's value is not NULL, ie disabled.

I'm using the tooltip in index mode with intersect turned to false so that the black line that is on the graph works, the black line came from this question.

I've tried a range of things from stackoverflow, but I have a feeling that none of the things i've tried have worked because of how the tooltip is set up.

Is it at all possible to do what I need here?

Upvotes: 0

Views: 1177

Answers (1)

NathanPB
NathanPB

Reputation: 745

Just change your options parameter a little bit.

tooltips: {
            mode: 'index',
            intersect: false,
            callbacks: {
                //returns a empty string if the label is "No Data"
                label: function(items, data){
                    let dataset = data.datasets[items.datasetIndex];
                    if(dataset.label !== "No Data") {
                        return `${dataset.label}: ${items.yLabel}`
                    } else {
                        return ""
                    }
                },

                //only returns something when at least one dataset yLabel is a valid number.
                title: function(t, e) {
                    let shouldDisplay = false;
                    t.forEach((it) => {
                       if(!isNaN(it.yLabel)) shouldDisplay = true;
                    });
                    if(shouldDisplay) {
                        return t[0].xLabel;
                    }
                }
            }
        },

There is probably a better way to optimize this, but I hope it helps

Upvotes: 1

Related Questions