D3.js is the most popular library for creating interactive charts in any web application. You can also use D3.js library in Lightning components for graphical representation of data. These charts can be used to give sales insights to a member ( Salesforce user) of the sales team. This article will show how can we leverage D3.js to build charts with a simple example.
First, let’s see the component code.
D3Charts.cmp
D3ChartsController.js
({ initD3Charts : function(component, event, helper) { var width = 960; var height = 500; // Create SVG element, we can't just use tag in lightning component // So creating one dynamically using jquery var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height); // Calling server-action to get the data var action = component.get("c.getData"); // Create a callback that is executed after // the server-side action returns action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { let data = response.getReturnValue(); console.log(data); // Render the returned data as a pie chart helper.renderChart( component, data ); } else if(state === "ERROR") { var errors = response.getError(); if (errors) { if (errors[0] && errors[0].message) { console.log("Error message: " + errors[0].message); } } else { console.log("Unknown error"); } } }); $A.enqueueAction(action); } })
D3ChartsHelper.js
({ renderChart : function( component, data ) { var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"), radius = Math.min(width, height) / 2, g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); var color = d3.scaleOrdinal(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); var pie = d3.pie() .sort(null) .value(function(d) { return d.candidates; }); var path = d3.arc() .outerRadius(radius - 10) .innerRadius(0); var label = d3.arc() .outerRadius(radius - 80) .innerRadius(radius - 80); var arc = g.selectAll(".arc") .data(pie(data)) .enter().append("g") .attr("class", "arc"); arc.append("path") .attr("d", path) .attr("fill", function(d) { return color(d.data.age); }); arc.append("text") .attr("transform", function(d) { return "translate(" + label.centroid(d) + ")"; }) .attr("dy", "0.35em") .text(function(d) { return d.data.age; }); } })
So, we have included d3.js library along with jquery.js and then called a server-side action when the script has loaded in order to fetch the chart data. In the defined callback function we passed that data to a helper function which rendered the chart.
D3ChartsController.apex
public class D3ChartsController { @AuraEnabled public static List getData(){ // For this example, it's just a static data but it can be generated // as per any business logic List lstData = new List(); lstData.add( new PieChart( '=65', 61 ) ); return lstData; } public class PieChart { @AuraEnabled public String age; @AuraEnabled public Integer candidates; public PieChart( String age, Integer candidates ) { this.age = age; this.candidates = candidates; } } }

Preview
Reference to resources –

I am certified Salesforce Developer with Sales and Service cloud certifications. I am a true believer in #GivingBack principle and a Salesforce enthusiast. I am working as a member of our #SalesforceOhana to learn and help other fellow Trailblazers of the community to grow and learn.
“I’m a true believer in karma. You get what you give, whether it’s bad or good.”
Hi Naval,
Thanks for the example.
However, I have a problem.
The afterScriptsLoaded=”{!c.initD3Charts}” isn’t being called/actioned.
I can’t see why.
Any suggestions?
It could be because of the LocerService.
Check the following link –
https://salesforce.stackexchange.com/questions/143819/ltngrequire-not-firing-afterscriptsloaded-with-locker-service-enabled
Hi Naval,
I found that the $Resource syntax doesn’t work.
Instead I used
(Couldn’t get a join to work either).
So the libraries load OK but I don’t see a pie chart.
I suspect a “div” or “canvas” is needed in the cmp but don’t know for sure.
Found it! I’d left off the curly braces in my Join statement. Oops!
I found a way to ‘tag’ to a thanks to joshbirk at https://gist.github.com/joshbirk/08be97d92b91c3bdc9e1
It seems D3 can select a if the name is prefixed with a ‘#’ sign.
add a div to your component:
then replace the dynamic scalable vector graphic creation with new code:
/*
var svg = d3.select(“body”)
.append(“svg”)
.attr(“width”, width)
.attr(“height”, height);
*/
var svg = d3.select(“#diagram”).append(“svg”)
.attr(“width”, width)
.attr(“height”, width)
.attr(“preserveAspectRatio”, “xMidYMid”)
.attr(“viewBox”, “-50 -50 1200 1200”);
nb: there’s a couple of extra attributes there that look fun and will need more research!
I can’t compile the apex controller, because of wrong return type in this line:
public static List getData(). There should probably be a ‘String’ (if the list of PieChart-s gets serialized) or just a ‘List’. Please confirm on either one.
In any case nothing is shown – the component simply renders empty.
It’s just a list and it’s automatically gets serialized when you get the result in the callback.
In the lightning component controller –
let data = response.getReturnValue();
variable ‘data’ will have an array of JS objects. You could be doing something wrong and that is leading the empty chart issue.