Search code examples
javascriptchart.jsreact-chartjs-2

Set a limit / max number for legends


Lets say I have a Donut chart with 5 items in data like this

const data = {
  labels: ['E-commerce', 'Enterprise', 'Green', 'Grey', 'Purple'],
  datasets: [
    {
      label: '# of Votes',
      data: [12, 19, 3, 5, 3],
      backgroundColor: ['#C07CC3', '#9C3848', '#9DDBAD', '#ADA8B6', '#606EDA'],
      borderWidth: 1,
    },
  ],
} 

I don't want it to show all the legends as I don't have space or whatever reason

How can I hide the Green and purple in this example?

I mean only from legends not from chart

enter image description here


Solution

  • I see two easy ways, how you could approach this problem:
    (I personally I would use the second option below, it is more configurable, but it needs just abit of coding)

    1. You can simply delete the labels you want to delete from the labels- array, and they won't show up in the legend.

      But keep in mind you would have to change the order of the data and backgroundColor arrays, to match this change.

      Here a short demo:

      const data = {
          labels: ['E-commerce',  'Enterprise', 'Grey'], // <-- just remove the unwanted labels
          datasets: [{
              data: [12, 19, 5, 3, 3], // <-- reorder
              backgroundColor: ['#C07CC3', '#9C3848',  '#ADA8B6', '#9DDBAD', '#606EDA'], // <-- reorder
              borderWidth: 1,
           }],
      };
      
      const config = {
          type: 'doughnut',
          data: data,
          options: {
              maintainAspectRatio: false,
              plugins: {
                  legend: {
                      position: 'right',
                      labels: {
                          usePointStyle: true,
                      },
                  }
              },
          }
      };
      
      new Chart(
          document.getElementById('chart'),
          config
      );
      <script src="//cdn.jsdelivr.net/npm/chart.js"></script>
      <div class="chart" style="height:184px; width:350px;">
          <canvas  id="chart" ></canvas>
      </div>

    2. Better and cleaner (but some coding is needed), you can filter out label-items, you don't want to display, with the function array filter. (details can be found in the documentation)

      UPDATED Alternative Version Demo:

      here only the Top 3 labels (limiting the amount of labels with the variable maxLabelsToShow) will be shown (sort order is descending, but changing this is would be easy)

    function getLabelsOnlyTopX(num, data, labels){
        let selectedLabels = []
      
        //we don't want to alter the order
        let helperData = [...data];
      
        //sort in descending order
        helperData.sort( (a,b) => b-a);
      
        //get top X Values
        helperData = helperData.slice(0, num);
      
        //get index for the data
        let indexes = data.map( (value, index) => ({value,index}) ).filter(item => helperData.some(n1 => n1 == item.value))
    
        //slecet only labels with the correct index  
        selectedLabels = labels.filter((value, index) => indexes.some( n => n.index == index))
      
        // just be sure that a maximum of num labels are sent
        return selectedLabels.slice(0, num);
    }
    
    let maxLabelsToShow = 3;
    let serverData = [12, 19, 3, 5, 3]
    let labels = ['E-commerce', 'Enterprise', 'Green', 'Grey', 'Purple'];
    
    // Calling the newly created function
    let showOnly = getLabelsOnlyTopX(maxLabelsToShow, serverData, labels);
    
    const data = {
        labels: labels,
        datasets: [{
            data: serverData,
            backgroundColor: ['#C07CC3', '#9C3848', 
                '#9DDBAD', '#ADA8B6', '#606EDA'],
            borderWidth: 1,
         }],
    };
    
    const config = {
        type: 'doughnut',
        data: data,
        options: {
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    position: 'right',
                    labels: {
                        usePointStyle: true,
                        /* FILTER function */
                        filter: function(item, chart) {
                            return showOnly.indexOf( item.text) > -1;
                        }
                    },
                }
            },
        }
    };
    
    new Chart(
        document.getElementById('chart'),
        config
    );
    <script src="//cdn.jsdelivr.net/npm/chart.js"></script>  
    <div class="chart" style="height:184px; width:350px;">
        <canvas  id="chart" ></canvas>
    </div>