1

I am trying to create a map hierarchy visual aura component using D3 library and d3 tree and d3.hierachy methods. The original code had circles in place for the nodes, but I want to append a div so that I can have a square box with information/fields placed within the div. The problem is that I cant seem to get any formatting to show up on the aura component. Maybe it has to do with the strict rules on interacting with the DOM in salesforce, however I am not sure because I'm still fairly new to development in general.

Here is a pic of the component:

Component

CSS

enter image description here

Relevant Js enter image description here

The commented code is of course the circle that was previously there and that I am trying to replace with a div having a border. Can I even do this within salesforce?

Component cmp

enter image description here

Helper js

({
drawOrgChart : function(component, event, helper) {

  var treeData ={
                  "name": "Durango Holding",
                  "children": [
                      { "name": "Durango Trucking"},
                      { "name": "Durango Leasing" },
                      { "name": "VW",
                        "children" : [
                            { "name" : "Golf"},
                            { "name" : "Beetle"}
                        ] 
                      },
                      { "name": "Hyundai"},
                   ]
                 };
  
  console.log(treeData);
    
 //setting the dimensions and margins of the diagram
 var margin = {top: 40, right:30, bottom:50, left:30};
 var width = 1260 - margin.left - margin.right;
 var height = 600 - margin.top - margin.bottom;
    
 //Declare a tree Layout and assign its size
 var treemap = d3.tree()
             .size([width, height]);
    
 //Assigns the data to hierarchy using parent-child relationships
 var nodes = d3.hierarchy(treeData, function(d){
                    return d.children;
                 });
 console.log(nodes);
    
 /*NOTE: This assigns a range of properties to each node including (node.data, node.depth, node.height, node.parent, node.children)
 We are telling the function to use the "children" element from treeData to generate property of the nodes. */
    
 //Map the node data to tree Layout
 nodes = treemap(nodes);
 console.log(nodes);
    
 
 //Append the Map(SVG) to the body of the Lightning Component
 var svg = d3.select("body")   
         .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
         .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
 //Add All Links between nodes
 var link = svg.selectAll(".link")
           .data(nodes.descendants().slice(1)) //We are not including the main 'root' node as since its drawn from child to parent.
           .enter()
           .append("path")
           .attr("class", "link")
           .attr("fill", "none") //Including all the styles directly here as the Style configured is not applied to lighting component.
           .attr("stroke", "#ccc")
           .attr("stroke-width", "2px")
               .attr("d", function(d){  //Here Attribute 'd' is used to describe the curve. Using Bezier Curve
                return "M" + d.x + "," + d.y
                    + "L" + d.x + "," + (d.y + d.parent.y) / 2
                    + " " + d.parent.x + "," + (d.y + d.parent.y) / 2
                    + " " + d.parent.x + "," + d.parent.y
            });
 console.log(nodes.descendants());
 console.log(nodes.descendants().slice(1));
    
 //Add Each Node as a Group - Ie, setting up a group
 var node = svg.selectAll(".node")
                   .data(nodes.descendants())
                   .enter()
                   .append("g")
                        .attr("class", "node node--leaf")
                    .attr("transform", function(d){
                            return "translate(" + d.x + "," + d.y + ")";
                    });
    
 //Add a circle to the node
 /*
 node.append("circle")
     .attr("r", 15)
     .attr("fill", "#fff")
     .attr("stroke", "steelblue")
     .attr("stroke-width", "3px");


node.append("div")
    .style("border","2px solid black");;



node.append("rect")
    .attr("height", 100)
    .attr("width", 225)
    .attr("fill", "none")
    .attr("stroke", "black")
    .style("stroke-width", 2)
    .attr("rx", 3);

                             */
node.append("div")
    .attr("class", "box");

    
 //Add Text to the node
 node.append("text")
     .attr("dy", ".35em")
     .attr("y", function(d){ return d.children ? -20 : 20;})
     .style("text-anchor", "middle")
     .text(function(d) {return d.data.name; });

}
})

error: enter image description here

code updated:

enter image description here

enter image description here

1 Answer 1

2

Your problem is here:

var svg = d3.select("body")   

You can't use document.body and apply styles to it, because it is protected by Locker Service, and you are reaching outside your component's container.

You need to provide a valid element within your own component:

<aura:component>
  <div aura:id="container">
  </div>
</aura:component>

And then hand that element to d3:

var svg = d3.select(component.find("container"))

You can also use a lightning:container, described in this answer.

2
  • ok I updated code but am getting an undefined error. Did I update it wrong?
    – Benton
    Mar 8, 2022 at 19:31
  • The updated code and error are in the og post also. At bottom. Thanks @sfdcfox
    – Benton
    Mar 8, 2022 at 19:38

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.