2

Why can not I draw a circle with d3.js in a lightning component?

appl.app:

<aura:application >
    <c:libComp/>
</aura:application>

comp.cmp:

<aura:component>
    <ltng:require scripts="{!$Resource.d3Lib}"
                  afterScriptsLoaded="{!c.drawACircle}" />
</aura:component>

compController.js:

({
    drawACircle: function () {
        //Make an SVG Container
        var svgContainer = d3.select("body").append("svg")
                                            .attr("width", 200)
                                            .attr("height", 200);

        //Draw the Circle
        var circle = svgContainer.append("circle")
                                 .attr("cx", 30)
                                 .attr("cy", 30)
                                 .attr("r", 20)
    }
});

According to this I am doing everything correctly.

But here is the error message:

Uncaught TypeError: Cannot read property 'document' of undefined throws at https://oobarbazanoo-dev-ed.lightning.force.com/resource/1527188162000/d3Lib:15:4187

enter image description here

In the d3Lib I put all that is written over here.

  • adding some debug info would probably help your cause and others to better help you – glls May 24 '18 at 18:40
  • Cannot read document, it looks like D3 was trying to manipulate DOM, – Pranay Jaiswal May 24 '18 at 19:22
  • @PranayJaiswal, yeah. What can I do about it? – oobarbazanoo May 24 '18 at 19:33
  • 1
    Ah, looks like I misread the error. I mistakenly though it was happening in your controller. As it stands, that error likely means that the version of D3 you're using isn't compatible with Locker Service. Try using an older version, or a newer version, or honestly, just write your own SVG code if all you need is a small handful of features. – sfdcfox May 24 '18 at 19:52
3

You can use lightning: container to accomplish this. Lightning:container was designed to use 3rd party libraries which are not locker service friendly in lightning components.

HTML file:

<html>
<head>
<script src="d3.v3.min.js"></script>

</head>

<body>
MyBody
</body>

<script src="use.js"></script>
</html>

use.js

var svgContainer = d3.select("body").append("svg")
                                .attr("width", 200)
                                .attr("height", 200);

//Draw the Circle
var circle = svgContainer.append("circle")
                     .attr("cx", 30)
                     .attr("cy", 30)
                     .attr("r", 20);

console.log(svgContainer);
console.log('circel drawn');

Manifest file for CSP:

{
    "landing-pages" : [
        {
            "path": "home.html",
            "content-security-policy-type": "Minimum"
        }
    ]
 }

and finnally the downloaded D3js file,refrenced in HTMl.

Create a zip of all those 4 files and upload as a static resouces named as "d3Demo".

enter image description here

And then in you lightning component/application refer the lightning:container as

<aura:application >
    <lightning:container src="{!$Resource.d3Demo+'/home.html'}" />

</aura:application>

Thasts it done. D3js in lightning components, no need to worry about locker services.

Source:https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/container_overview.htm

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.