Custom Legend with ChartJS v2.0

I hope this will helpful you

var configd = {
    type: 'doughnut',
    data: {
        datasets: [{
            data: [
                50,
                60,
                20
            ],           
            backgroundColor: [
                '#33b35a',
                "#ffce56",
                "#4bc0c0",
                "#CDDC39",
                "#9C27B0",
                "#fb7145",
                "#5971f9"
            ],
            label: 'Energy usage'
        }],
        labels: [
            'E1',
            'E2',
            'E3'
        ]
    },
    options: {
        responsive: true,
        legend: {
            display: false
        },
        legendCallback: function (chart) {             
            // Return the HTML string here.
            console.log(chart.data.datasets);
            var text = [];
            text.push('<ul class="' + chart.id + '-legend">');
            for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
                text.push('<li><span id="legend-' + i + '-item" style="background-color:' + chart.data.datasets[0].backgroundColor[i] + '"   onclick="updateDataset(event, ' + '\'' + i + '\'' + ')">');
                if (chart.data.labels[i]) {
                    text.push(chart.data.labels[i]);
                }
                text.push('</span></li>');
            }
            text.push('</ul>');
            return text.join("");
        },
        title: {
            display: false,
            text: 'Chart.js Doughnut Chart'
        },
        animation: {
            animateScale: true,
            animateRotate: true
        },
        tooltips: {
            mode: 'index',
            intersect: false,
            callbacks: {
                label: function (tooltipItem, data) {
                    let label = data.datasets[tooltipItem.datasetIndex].label + ' - ' + data.labels[tooltipItem.index];
                    let datasetLabel = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
                    return label + ': ' + datasetLabel.toLocaleString();
                }
            }
        },
    }
};

 var ctxd = document.getElementById('canvas').getContext('2d');
    
    window.myDoughnut = new Chart(ctxd, configd);
    $("#do_legend").html(window.myDoughnut.generateLegend());

// Show/hide chart by click legend
updateDataset = function (e, datasetIndex) {    
    var index = datasetIndex;
    var ci = e.view.myDoughnut;
    var meta = ci.getDatasetMeta(0);    
    var result= (meta.data[datasetIndex].hidden == true) ? false : true;
    if(result==true)
    {
        meta.data[datasetIndex].hidden = true;
        $('#' + e.path[0].id).css("text-decoration", "line-through");
    }else{
        $('#' + e.path[0].id).css("text-decoration","");
        meta.data[datasetIndex].hidden = false;
    }
     
    ci.update();   
};
#do_legend{
   height:62px;
}

#do_legend{
    width:100%;     
}

#do_legend> ul{
    padding: 0;
    text-align: center;
}
 

#do_legend {   
  width:100%;
  bottom:10%;
}
#do_legend li {
    cursor: pointer;
    margin: 4px 3px;
    display: inline-table;
}
#do_legend li span {
    position: relative;
    padding: 3px 10px;
    border-radius: 13px;
    color: white;
    z-index: 2;
    font-size: 11px;
}

#do_legend{
    height: 62px;
    overflow-y: auto;
}

.donut-area{
    height:calc(100% - 62px)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>


<div style="width:40%">
   <div id="do_legend"></div>
  <canvas id="canvas"></canvas>
</div>

Codepen Example


If people come here looking for a solution for this in ChartJS 3.6.0. (Maybe other versions too)

They offer an HTML legend where you can specify the exact HTML you want using the plugins option. Here is an example of the configuration along with the link to the documentation below.

  const config = {
  type: 'line',
  data: data,
  options: {
    plugins: {
      htmlLegend: {
        // ID of the container to put the legend in
        containerID: 'legend-container',
      },
      legend: {
        display: false,
      }
    }
  },
  plugins: [htmlLegendPlugin],
};

ChartJS HTML Legend


If you guys run through this post and tried the posted answer and didn't work, try this one:

  legendCallback: function(chart) {
    var text = [];
    text.push('<ul>');
    for (var i=0; i<chart.data.datasets.length; i++) {
      console.log(chart.data.datasets[i]); // see what's inside the obj.
      text.push('<li>');
      text.push('<span style="background-color:' + chart.data.datasets[i].borderColor + '">' + chart.data.datasets[i].label + '</span>');
      text.push('</li>');
    }
    text.push('</ul>');
    return text.join("");
  },

Then add this below:

document.getElementById('chart-legends').innerHTML = myChart.generateLegend();

To create the legends. Make sure you have an element <div id="chart-legends"></div>


There is a legendCallback function:

legendCallback Function function (chart) { }
Function to generate a legend. Receives the chart object to generate a legend from. Default implementation returns an HTML string.

Details can be found here

see this issue for the default legend callback:

legendCallback: function(chart) { 
    var text = []; 
    text.push('<ul class="' + chart.id + '-legend">'); 
    for (var i = 0; i < chart.data.datasets.length; i++) { 
        text.push('<li><span style="background-color:' + 
                   chart.data.datasets[i].backgroundColor + 
                   '"></span>'); 
        if (chart.data.datasets[i].label) { 
            text.push(chart.data.datasets[i].label); 
        } 
        text.push('</li>'); 
    } 
    text.push('</ul>'); 
    return text.join(''); 
}