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.
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!
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:
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.
I need a area chart with using angular directive and data is fetched from database but the problem is after fetching the data ,chart is not appear and when i use static data chart appears fine.And chart would update after 10 seconds that is my requirement.
var myapp=angular.module('myapp',['ngRoute']);
myapp.controller('GraphController',
function(dataFactory,$scope,$http,$timeout){
var getData=function() {
dataFactory.httpRequest('/graph').then(function (data) {
console.log(JSON.stringify(data));
$scope.myModel=JSON.stringify(data);
$timeout(getData, 1000);
});
}
$scope.xkey = 'id';
$scope.ykeys = ['id', 'value'];
$scope.labels = ['ID', 'Value'];
$timeout(getData, 1000);
/* Static data and when these static data are use in getData function ,it didnot work.
$scope.myModel = [
{"id":21,"yr":2000,"value":80},
{"id":1,"yr":2001,"value":5},
{"id":2,"yr":2002,"value":6},
{"id":3,"yr":2003,"value":17},
{"id":4,"yr":2004,"value":5},
{"id":5,"yr":2005,"value":22},{"id":7,"yr":2006,"value":41},
{"id":9,"yr":2007,"value":11},{"id":10,"yr":2008,"value":33},
{"id":8,"yr":2009,"value":77},{"id":6,"yr":2010,"value":55},
{"id":11,"yr":2011,"value":55},{"id":12,"yr":2012,"value":66},
{"id":13,"yr":2013,"value":77},{"id":14,"yr":2014,"value":50},
{"id":15,"yr":2015,"value":22},{"id":16,"yr":2016,"value":77},
{"id":17,"yr":2017,"value":41},{"id":18,"yr":2018,"value":20},
{"id":19,"yr":2019,"value":9},{"id":20,"yr":2020,"value":2},
{"id":23,"yr":2022,"value":1}
];*/
});
myapp.directive('areachart',function(){ //directive name must be in small letters
return {
// required to make it work as an element
restrict: 'E',
template: '<div></div>',
replace: true,
link:function($scope,element,attrs)
{
var data=$scope[attrs.data],
xkey=$scope[attrs.xkey],
ykeys=$scope[attrs.ykeys],
labels=$scope[attrs.labels];
Morris.Area({
element:element,//element means id #
data:data,
xkey:xkey,
ykeys:ykeys,
labels:labels,
parseTime: false,
ymax:120,//Max. bound for Y-values
lineColors: ['#0b62a4', '#D58665'],//Array containing colors for the series lines/points.
smooth: true,//Set to false to disable line smoothing.
hideHover: 'auto',//Set to false to always show a hover legend.
pointSize: 4,//Diameter of the series points, in pixels.s
axes:true,//Set to false to disable drawing the x and y axes.
resize: true,//Set to true to enable automatic resizing when the containing element resizes
fillOpacity:1.0,//Change the opacity of the area fill colour. Accepts values between 0.0 (for completely transparent) and 1.0 (for completely opaque).
grid:true,//Set to false to disable drawing the horizontal grid lines.
});
}
}
})
Html Page
<body ng-app="myapp">
<div ng-controller="GraphController">
<AreaChart xkey="xkey" ykeys="ykeys" labels="labels" data="myModel"></AreaChart>
</div>
</body>
Angularjs MVC. Try this:
$scope.dt = angular.fromJson(sReturn.data);
Works for me.
try this $scope.myModel=JSON.parse(data); insted of $scope.myModel=JSON.stringify(data);
I am using ChartJS with Angular (with this angular directive: http://jtblin.github.io/angular-chart.js).
I wanted to know if it is possible to put a placeholder from see when the chart data are all 0.
For example I have a chart with
$scope.data = [0,0,0];
$scope.labels = ["first", "second", "third"];
Is possible to print only the placeholder? or put one by default?
You can trun on the legend and override the legend template to show the values in the legend
$scope.options = {
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%>: <%=segments[i].value%><%}%></li><%}%></ul>"
};
If you want to show the value only if they are 0, just add an if condition
$scope.options = {
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%if(segments[i].value === 0){%>: <%=segments[i].value%><%}}%></li><%}%></ul>"
};
Working fiddle - http://jsfiddle.net/s2t3quwp/
If all your data points are 0, you will see not chart, but you can still see the legend.
Custom colours for doughnut chart is not showing in legend, rather legends take arbitrary colours. How can I make it pickup those custom colours?
app.controller("ExampleController", ["$scope", function ($scope) {
$scope.pie = [
{key: "Passed", y: 2},
{key: "Failed", y: 3}
];
var colorArray = ['red', 'green'];
$scope.colorFunction = function() {
return function(d, i) {
return colorArray[i];
};
};
...x y functions ...
}]);
HTML
...
<nvd3-pie-chart
data="pie"
id="donutLabelsOutsideExample"
width="450"
height="350"
x="xFunction()"
y="yFunction()"
donut="true"
showLabels="true"
showLegend="true"
donutLabelsOutside="true"
labelType="percent"
color="colorFunction()">
<svg height="250"></svg>
</nvd3-pie-chart>
...
The source code for the pie chart contains an attribute for legendcolor, so you can try adding that attribute.
legendcolor="colorFunction()"
Why it works:
In the controller of pieChart there is a call to checkElementID which in turn calls configureLegend
configureLegend is found in source code and has the following code
chart.legend.color(attrs.legendcolor === undefined ? nv.utils.defaultColor() : scope.legendcolor());
attrs.legendcolor is pulled from your directive attribute.
Good morning
I am using the angularjs-nvd3-directives, which is great, but I am having difficulties when setting the color of a multi bar chart (http://cmaurer.github.io/angularjs-nvd3-directives/multi.bar.chart.html).
The show legend works well:
<div ng-controller="ExampleCtrl">
<nvd3-multi-bar-chart
data="exampleData"
id="showLegendExample"
width="550"
height="300"
showXAxis="true"
showYAxis="true"
xAxisTickFormat="xAxisTickFormatFunction()"
showLegend="true">
<svg></svg>
</nvd3-multi-bar-chart>
</div>
But when I add this option in conjunction with color="colorFunction()" where,
var colorArray = ['#FF0000', '#0000FF', '#FFFF00', '#00FFFF'];
$scope.colorFunction = function() {
return function(d, i) {
return colorArray[i];
};
}
The color of the chart objects updates, but not legend. Is this a limitation of angularjs-nvd3-directives, that I can either set the color or have a legend and not both, or am I missing something?