[Chartjs]-How to show second set of labels to Chart.js doughtnut chart?

2👍

You have to generate the legend labels yourself by defining a legend.labels.generateLabels function together with a legend.onClick function that takes care of hiding and showing individual pie slices. This could look as follows:

legend: {
  labels: {
    generateLabels: () => {
      let labels = [];
      config.data.datasets.forEach((ds, iDs) => labels = labels.concat(ds.labels.map((l, iLabel) => ({
        datasetIndex: iDs,
        labelIndex: iLabel,
        text: l,
        fillStyle: ds.backgroundColor[iLabel],
        hidden: employeesGraph ? employeesGraph.getDatasetMeta(iDs).data[iLabel].hidden : false,
        strokeStyle: '#fff'
      }))));
      return labels;
    }
  },
  onClick: (event, legendItem) => {
    const metaData = employeesGraph.getDatasetMeta(legendItem.datasetIndex).data;
    metaData[legendItem.labelIndex].hidden = !metaData[legendItem.labelIndex].hidden;
    employeesGraph.update();
  }
},

Please have a look at your amended code below:

var platform_labels = ["Tablet", "Ordenador"];
var platform_dataset = [14, 5];
var os_labels = ["Android", "Windows", "GNU\/Linux"];
var os_dataset = [14, 4, 1];
var devices_labels = ["Tablet", "Ordenador", "Android", "Windows", "GNU\/Linux"];

var chartColors = {
  red: 'rgb(255, 99, 132)',
  orange: 'rgb(255, 159, 64)',
  yellow: 'rgb(255, 205, 86)',
  green: 'rgb(75, 192, 192)',
  blue: 'rgb(54, 162, 235)',
  purple: 'rgb(153, 102, 255)',
  grey: 'rgb(201, 203, 207)'
};

var config = {
  type: 'doughnut',
  data: {
    datasets: [{
      data: platform_dataset,
      backgroundColor: [
        chartColors.red,
        chartColors.orange,
      ],
      label: 'Platform',
      labels: platform_labels
    }, {
      data: os_dataset,
      backgroundColor: [
        chartColors.purple,
        chartColors.green,
        chartColors.blue
      ],
      label: 'OS',
      labels: os_labels
    }],
    labels: devices_labels
  },
  options: {
    legend: {
      labels: {
        generateLabels: () => {
          let labels = [];
          config.data.datasets.forEach((ds, iDs) => labels = labels.concat(ds.labels.map((l, iLabel) => ({
            datasetIndex: iDs,
            labelIndex: iLabel,
            text: l,
            fillStyle: ds.backgroundColor[iLabel],
            hidden: employeesGraph ? employeesGraph.getDatasetMeta(iDs).data[iLabel].hidden : false,
            strokeStyle: '#fff'
          }))));
          return labels;
        }
      },
      onClick: (event, legendItem) => {
        const metaData = employeesGraph.getDatasetMeta(legendItem.datasetIndex).data;
        metaData[legendItem.labelIndex].hidden = !metaData[legendItem.labelIndex].hidden;
        employeesGraph.update();
      }
    },
    tooltips: {
      callbacks: {
        label: function(tooltipItem, data) {
          var dataset = data.datasets[tooltipItem.datasetIndex];
          var index = tooltipItem.index;
          return dataset.labels[index] + ": " + dataset.data[index];
        }
      }
    }
  }
};
var ctx = document.getElementById('deviceChart').getContext('2d');
var employeesGraph = new Chart(ctx, config);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="deviceChart" height="120"></canvas>

1👍

The second set of labels are striked through because chartjs see’s them as hidden, i.e. they have no values so are not rendered and the labels are only getting drawn from the first dataset.

There is a few ways around this, you could either disable the legend and then create a custom legend but I’m not sure if this will grab all of the labels:

var chart = new Chart(ctx, {
        type: 'line',
        data: data,
        options: {
            legend: {
                display: false
            },
            legendCallback: function(chart) {
                var text = [];
                text.push('<ul>');
                for (var i=0; i<devices_labels.length; i++) {
                    text.push('<li>');
                    text.push('<span style="background-color:' + 
                    chart.data.datasets[i].borderColor + '">' + devices_labels[i] + 
                    '</span>');
                    text.push('</li>');
                }
                text.push('</ul>');
                return text.join("");
            }
        }
    });

Or you could extend chartjs to change the behaviour of labels for hidden data:- change legend item style when dataset is hidden

Or the simplest way is to just add in some dummy data, to your first dataset:-

var platform_labels = ["Tablet","Ordenador"];
  var platform_dataset = [14, 5, 0, 0, 0];
  var os_labels = ["Android","Windows","GNU\/Linux"];
  var os_dataset = [14,4,1];
  var devices_labels = ["Tablet","Ordenador","Android","Windows","GNU\/Linux"];
  
  
      var chartColors = {
          red: 'rgb(255, 99, 132)',
          orange: 'rgb(255, 159, 64)',
          yellow: 'rgb(255, 205, 86)',
          green: 'rgb(75, 192, 192)',
          blue: 'rgb(54, 162, 235)',
          purple: 'rgb(153, 102, 255)',
          grey: 'rgb(201, 203, 207)'
      };


      var config = {
          type: 'doughnut',
          data: {
              datasets: [{
                  data: platform_dataset,
                  backgroundColor: [
                      chartColors.red,
                      chartColors.orange,
                      chartColors.purple,
                      chartColors.green,
                      chartColors.blue
                  ],
                  label: 'Platform',
                  labels: platform_labels
              }, {
                  data: os_dataset,
                  backgroundColor: [
                      chartColors.purple,
                      chartColors.green,
                      chartColors.blue
                  ],
                  label: 'OS',
                  labels: os_labels
              }],
              labels: devices_labels
          }
      };
      var ctx = document.getElementById('deviceChart').getContext('2d');
      var employeesGraph = new Chart(ctx, config);

Leave a comment