13

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

TylerH
  • 20,799
  • 66
  • 75
  • 101
Altro
  • 878
  • 1
  • 7
  • 23
  • 2
    A cursory aside: a chart with missing labels wouldn't be effective. Plus pie/donut charts are pretty bad at showing relative values (even if you did add the values to the chart) - you may want to change it to a bar chart with labelled axes instead. – Andy Dec 13 '22 at 05:32
  • 3
    This isn't an answer to your question but yeah consider what Andy said. I once did the same thing all excited that I could visualize data but once you get smaller partitions people get worse and worse at estimating what the data actually looks like. Read: https://scc.ms.unimelb.edu.au/resources/data-visualisation-and-exploration/no_pie-charts#:~:text=Pies%20and%20doughnuts%20fail%20because,important)%20are%20tricky%20to%20show. – Bowiemtl Dec 13 '22 at 10:39
  • 1
    Even if possible, having some labels is detrimental to the chart's goal. If you have trouble with the spacing, try moving the label into another place or just don't show it and add it manually yourself. Information is information and not aesthetics criterias should be set to ofuscate it. – Lomefin Dec 16 '22 at 04:21
  • what happens if you put an empty string on the labels array ? – Franco Aguilera Dec 31 '22 at 05:27

1 Answers1

5

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>
winner_joiner
  • 12,173
  • 4
  • 36
  • 61
  • The second one would be good but the point is that I will get data from backend and I will not know by labels which one is larger so that I would hide that, I should sort that showOnly by their data, and I cannot do that with none of your 2 answers – Altro Dec 14 '22 at 21:05
  • @Altro I updated my anser with a extra function, that selects the top X labels to display. I hope this helps for your usecase – winner_joiner Dec 15 '22 at 08:54
  • @Altro I just wanted to know, if my udated solution helped, or if you need some help. _(the created funtion can be tweaked)_ – winner_joiner Dec 21 '22 at 04:58