Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select All and Unselect Option for chart.js

I'm Working on Chart.js, wanted to implement Select All and Unselect All option for labels. I'm trying to find it out but couldn't get anything such.

Please do help me out if anything such feature can be implemented.

like image 802
David Avatar asked Mar 13 '18 06:03

David


3 Answers

V3 Answer

You can use a custom generateLabels function together with a custom onClick to get it as an extra legendItem like so:

const defaultLegendClickHandler = Chart.defaults.plugins.legend.onClick;
const pieDoughnutLegendClickHandler = Chart.controllers.doughnut.overrides.plugins.legend.onClick;

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        borderColor: 'pink'
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderColor: 'orange'
      }
    ]
  },
  options: {
    plugins: {
      legend: {
        onClick: (evt, legendItem, legend) => {
          const type = legend.chart.config.type;
          let allLegendItemsState = [];

          if (legendItem.text === 'hide all datasets' || legendItem.text === 'show all datasets') {
            if (typeof legend.hideAll === 'undefined') {
              legend.hideAll = false;
            }

            legend.chart.data.datasets.forEach((dataset, i) => {
              legend.chart.setDatasetVisibility(i, legend.hideAll)
            });

            legend.hideAll = !legend.hideAll;
            legend.chart.update();

            return;
          }

          if (type === 'pie' || type === 'doughnut') {
            pieDoughnutLegendClickHandler(evt, legendItem, legend)
          } else {
            defaultLegendClickHandler(evt, legendItem, legend);
          }

          allLegendItemsState = legend.chart.data.datasets.map((e, i) => (legend.chart.getDatasetMeta(i).hidden));

          if (allLegendItemsState.every(el => !el)) {
            legend.hideAll = false;
            legend.chart.update();
          } else if (allLegendItemsState.every(el => el)) {
            legend.hideAll = true;
            legend.chart.update();
          }
        },
        labels: {
          generateLabels: (chart) => {
            const datasets = chart.data.datasets;
            const {
              labels: {
                usePointStyle,
                pointStyle,
                textAlign,
                color
              }
            } = chart.legend.options;

            const legendItems = chart._getSortedDatasetMetas().map((meta) => {
              const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);

              return {
                text: datasets[meta.index].label,
                fillStyle: style.backgroundColor,
                fontColor: color,
                hidden: !meta.visible,
                lineCap: style.borderCapStyle,
                lineDash: style.borderDash,
                lineDashOffset: style.borderDashOffset,
                lineJoin: style.borderJoinStyle,
                strokeStyle: style.borderColor,
                pointStyle: pointStyle || style.pointStyle,
                rotation: style.rotation,
                textAlign: textAlign || style.textAlign,
                datasetIndex: meta.index
              };
            });

            legendItems.push({
              text: (!chart.legend.hideAll || typeof chart.legend.hideAll === 'undefined') ? 'hide all datasets' : 'show all datasets',
              fontColor: color,
              fillStyle: 'turquoise', // Box color
              strokeStyle: 'turquoise', // LineCollor around box
            });

            return legendItems;
          }
        }
      }
    }
  }
}

const 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.6.0/chart.js"></script>
</body>
like image 78
LeeLenalee Avatar answered Sep 20 '22 21:09

LeeLenalee


If you need to show/hide charts selecting/unselecting all labels here is an example:

var barChartData = {
  labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
  datasets: [{
    label: 'One',
    backgroundColor: 'rgba(206, 0, 23, 1)',
    data: [0, 1, 3, 0, 2, 0, 0, 2, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 2, 1, 0, 1, 2, 1, 1, 0, 0, 0, 2, 2, 0, 3]
  }, {
    label: 'Two',
    backgroundColor: 'rgba(206, 0, 23, 0.75)',
    data: [0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
  }, {
    label: 'Three',
    backgroundColor: 'rgba(206, 0, 23, 0.5)',
    data: [0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1]
  }]

};
var ctx = document.getElementById('canvas').getContext('2d');
var chartInstance = new Chart(ctx, {
  type: 'bar',
  data: barChartData,
  options: {
    title: {
      display: false,
    },
    responsive: true,
    scales: {
      xAxes: [{
        stacked: true,
      }],
      yAxes: [{
        stacked: true
      }]
    }
  }
});

$("#toggle").click(function() {
	 chartInstance.data.datasets.forEach(function(ds) {
    ds.hidden = !ds.hidden;
  });
  chartInstance.update();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<button id="toggle">show/hide all</button>
<canvas id="canvas" height="500" width="800"></canvas>

Jsfiddle: https://jsfiddle.net/beaver71/00q06vjp/

Credits: see https://github.com/chartjs/Chart.js/issues/3009


Update: for pie chart use "meta", see: https://jsfiddle.net/beaver71/u0y0919b/

like image 25
beaver Avatar answered Oct 15 '22 09:10

beaver


For ChartJS 2.9.3, this works as requested by David in the comments:

const chart = ...
chart.data.datasets.forEach(dataset => {
  Object.keys(dataset._meta).forEach(key => {
    const current = !dataset._meta[key].hidden
    dataset._meta[key].hidden = current || null
  })
})
chart.update()

Toggles all with a button, while playing nicely with the individual toggling in the chart legend.

like image 2
ivom Avatar answered Oct 15 '22 09:10

ivom