How to make a custom legend in angular-chart.js Pie Chart

Christa picture Christa · Oct 25, 2016 · Viewed 10.9k times · Source

I used angular-chart.js in my website to create a Pie chart, and I would like to customize the legend. By default, the legend shows the color and the label. (As shown in the picture below) I would like to add the value/data of that label, like what it shown in the tooltip of the chart.

enter image description here

This is my HTML code:

<canvas id="pie" class="chart chart-pie"
   chart-data="chartData" chart-labels="chartLabels" chart-options="chartOptions">
</canvas>

Based on the angular-chart.js documentation, legend is now a Chart.js option so the chart-legend attribute has been removed.

That is why, in my JS code I've tried to add generateLabels, just in case this is what I need to customize the legend:

$scope.chartOptions = { 
        legend: {
          display: true,
          labels: {
            generateLabels: function(chart){
              console.log(chart.config);
            }
          }
        }
      };

But whenever I add this lines, it will not show the chart. I think it is an error or something. And I'm not sure, if generateLabels is the right option that I needed.

Can somebody teach me the right way to customize the legend to achieve what I wanted?

Thanks in advance!

Answer

Keno picture Keno · Oct 26, 2016

Let me try shedding some light/answering your question:

generateLabels: does make custom labels,and replaces templates from v1 but in order to use it you have to get your chart information and reimplement legend labels adhering to the Legend Item Interface found in the docs and code. Sounds a bit cryptic, but in practice is somehow simple and goes like this:

var theHelp = Chart.helpers;
// You need this for later

// Inside Options:
legend: {
display: true,    
// generateLabels changes from chart to chart,  check the source, 
// this one is from the doughnut :
// https://github.com/chartjs/Chart.js/blob/master/src/controllers/controller.doughnut.js#L42
labels: {
  generateLabels: function(chart) {
    var data = chart.data;
    if (data.labels.length && data.datasets.length) {
      return data.labels.map(function(label, i) {
        var meta = chart.getDatasetMeta(0);
        var ds = data.datasets[0];
        var arc = meta.data[i];
        var custom = arc && arc.custom || {};
        var getValueAtIndexOrDefault = theHelp.getValueAtIndexOrDefault;
        var arcOpts = chart.options.elements.arc;
        var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
        var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
        var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
          return {
          // And finally : 
          text: ds.data[i] + "% of the time " + label,
          fillStyle: fill,
          strokeStyle: stroke,
          lineWidth: bw,
          hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
          index: i
        };
      });
    }
    return [];
  }
}
}

Result: Chart.js pie Custom Legend

Codepen: Chart.js Pie Chart Custom Legend Labels

There are other alternatives, if you notice on the pen/pie, the slices also have data information, that is from a plugin (check the pen)

Still another option, is to render the legend labels off canvas,for instance:

myPieChart.generateLegend();

Which gives you this Html:

"<ul class='0-legend'><li><span style='background-color:black'>  </span>she returns it </li><li><span style='background-color:white'></span>she keeps it</li></ul>"

I haven't tried it, but I think you can modify it with the global method for your data Legend on the callback an it will give you a block of Html you can insert off canvas.