function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Chinmayi GowdaChinmayi Gowda 

Aura component to show role leve orgchart pictorical diagram

Hi all

I am working on a Aura component framwork where i need to show the Hirarchy wise pictorical diagram, with some struggle i was able to achive the functionality but i am not display subnodes for child node, like below diagram

any help will be very helpfull

User-added image
below is what is i have achieved

User-added image
 
public class OrgChartController
{
    @AuraEnabled
    public static String getContacts(String recordId)
    {
        List<BindNodes> bindNodesWrapperList = new List<BindNodes>();
        if(!String.isBlank(recordId))
        {
            Account currentAccount = [Select id,name,Phone from Account where id =: recordId limit 1];
            if(currentAccount!=null)
            {
                String AccountName = '';
                String AccountPhone ='';
                if(currentAccount.name!=null)
                {
                    AccountName =currentAccount.name;
                }
                if(currentAccount.Phone!=null)
                {
                    AccountPhone = String.valueOf(currentAccount.Phone);
                }
                bindNodesWrapperList.add(getMasterAccount(AccountName,AccountPhone));
            }
            set<string> setid = new set<string>();
            List<Contact> contactList = [SELECT Id, FirstName,
                                        LastName, Role__c, Status1__c FROM Contact WHERE Accountid =: recordId ORDER BY FirstName];
            if(!contactList.isEmpty())
            {
                for(Contact objcontact : contactList)
                {
                    if(objcontact.id != null)
                    {
                        setid.add(objcontact.id);
                    }
                }
                bindNodesWrapperList.addAll(getBindNodesContact(contactList,setid));
            }
        }
        if(!bindNodesWrapperList.isEmpty())
        {
            return JSON.serialize(bindNodesWrapperList);
        }
        return '';
    }
    public static BindNodes.NodeIcon getNodeIcon()
    {
        BindNodes.NodeIcon currentAccountNodeIcon = new BindNodes.NodeIcon();
        currentAccountNodeIcon.icon='';
        currentAccountNodeIcon.size=0;
        return currentAccountNodeIcon;
    }
    public static BindNodes.BorderColor getBorderColorMain()
    {
        BindNodes.BorderColor currentAccBorderColorMain = new BindNodes.BorderColor();
        currentAccBorderColorMain.red =15;
        currentAccBorderColorMain.green =140;
        currentAccBorderColorMain.blue =121;
        currentAccBorderColorMain.alpha =1;
        return currentAccBorderColorMain;
    }
    public static BindNodes.BorderColor getBorderColorNodeImage()
    {
        BindNodes.BorderColor currentAccBorderColorNodeImage = new BindNodes.BorderColor();
        currentAccBorderColorNodeImage.red =19;
        currentAccBorderColorNodeImage.green =123;
        currentAccBorderColorNodeImage.blue =128;
        currentAccBorderColorNodeImage.alpha =1;
        return currentAccBorderColorNodeImage;
    }
    public static BindNodes.BorderColor getBorderColorconnector()
    {
        BindNodes.BorderColor currentAccBorderColorconnector = new BindNodes.BorderColor();
        currentAccBorderColorconnector.red =220;
        currentAccBorderColorconnector.green =189;
        currentAccBorderColorconnector.blue =207;
        currentAccBorderColorconnector.alpha =1;
        return currentAccBorderColorconnector;
    }
    public static BindNodes.BorderColor getAccountBGColor()
    {
        BindNodes.BorderColor currentAccbgColor = new BindNodes.BorderColor();
        currentAccbgColor.red =235;
        currentAccbgColor.green =143;
        currentAccbgColor.blue =70;
        currentAccbgColor.alpha =1;
        return currentAccbgColor;
    }
    public static BindNodes.BorderColor getContactBGColor()
    {
        BindNodes.BorderColor currentContactbgColor = new BindNodes.BorderColor();
        currentContactbgColor.red =68; //160, 148, 237 ,1
        currentContactbgColor.green =212;
        currentContactbgColor.blue =59;
        currentContactbgColor.alpha =1;
        return currentContactbgColor;
    }
    public static BindNodes.NodeImage getNodeImage(BindNodes.BorderColor currentAccBorderColorNodeImage)
    {
        BindNodes.NodeImage bindNodeImage = new BindNodes.NodeImage();
        bindNodeImage.url = '';
        bindNodeImage.width = 100;
        bindNodeImage.height = 100;
        bindNodeImage.centerTopDistance = 0;
        bindNodeImage.centerLeftDistance = 0;
        bindNodeImage.cornerShape = 'CIRCLE';
        bindNodeImage.shadow = false;
        bindNodeImage.borderWidth = 0;
        bindNodeImage.borderColor = currentAccBorderColorNodeImage;
        return bindNodeImage;
    }    
    public static BindNodes getNode(BindNodes.NodeIcon currentAccountNodeIcon,BindNodes.BorderColor currentAccBorderColorMain,BindNodes.BorderColor currentAccBorderColorNodeImage,BindNodes.BorderColor currentAccBorderColorconnector,BindNodes.BorderColor currentAccbgColor,BindNodes.NodeImage bindNodeImage)
    {
       
        BindNodes currentAccount = new BindNodes();
      //  currentAccount.nodeId = 'O-1';
     //   currentAccount.parentNodeId = null;
        currentAccount.width = 342;
        currentAccount.height= 146;
        currentAccount.borderWidth= 1;
        currentAccount.borderRadius= 5;
        currentAccount.connectorLineWidth=5;
        currentAccount.dashArray='';
        currentAccount.expanded= false;
        currentAccount.directSubordinates=1;
        currentAccount.totalSubordinates=1;
        currentAccount.borderColor = currentAccBorderColorMain;
        currentAccount.backgroundColor=currentAccbgColor;
        currentAccount.nodeImage = bindNodeImage;
        currentAccount.nodeIcon = currentAccountNodeIcon;
//        currentAccount.template ='<div>\n<div style=\"margin-left:70px;\n margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\">'+AccountName+' </div>\n<div style=\"margin-left:70px;\n margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\">'+phone+' </div>\n</div>';
        currentAccount.connectorLineColor = currentAccBorderColorconnector;              
        return currentAccount;
    }
    public static BindNodes getMasterAccount(String AccountName,String phone)
    {
        BindNodes.NodeIcon currentAccountNodeIcon = getNodeIcon();
   
        BindNodes.BorderColor currentAccBorderColorMain =getBorderColorMain();
       
        BindNodes.BorderColor currentAccBorderColorNodeImage = getBorderColorNodeImage();
       
        BindNodes.BorderColor currentAccBorderColorconnector = getBorderColorconnector();
           
        BindNodes.BorderColor currentAccbgColor = getAccountBGColor();
       
        BindNodes.NodeImage bindNodeImage = getNodeImage(currentAccBorderColorNodeImage);
               
        BindNodes currentAccount = getNode(currentAccountNodeIcon,currentAccBorderColorMain,currentAccBorderColorNodeImage,currentAccBorderColorconnector,currentAccbgColor,bindNodeImage);
        currentAccount.nodeId = 'O-1';
        currentAccount.parentNodeId = null;
        currentAccount.template ='<div>\n<div align="center" style=\" margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\">'+AccountName+' </div>\n<div align="center" style=\" margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\">'+phone+' </div>\n</div>';
        return currentAccount;

    }
    public static List<BindNodes> getBindNodesContact(List<Contact> contactList,set<string> setid)
    {
        List<BindNodes> BindNodesList = new List<BindNodes>();
   
        BindNodes.NodeIcon currentAccountNodeIcon = getNodeIcon();
   
        BindNodes.BorderColor currentAccBorderColorMain =getBorderColorMain();
       
        BindNodes.BorderColor currentAccBorderColorNodeImage = getBorderColorNodeImage();
       
        BindNodes.BorderColor currentAccBorderColorconnector = getBorderColorconnector();
           
        BindNodes.BorderColor currentAccbgColor = getAccountBGColor();
       
        BindNodes.NodeImage bindNodeImage = getNodeImage(currentAccBorderColorNodeImage);
   
        BindNodes.BorderColor currentContactbgColor = getContactBGColor();
        Integer i = 2;
        String baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
        baseUrl = baseUrl + '/lightning/r/Contact/';
        map<id,list<contact>> mapcontact = new map<id,list<contact>>();
        list<contact> lstobjconts = new list<contact>();
        set<id> setnewids = new set<id>();
        if(setid.size() > 0)
        {
            for(integer j=1;j<=setid.size(); j++)
            {
                for(contact objcon1 : [select id,Firstname,lastname,Status1__c,ReportsToId,Role__c from contact where ReportsToId =:setid])
                {
                    if (setid.contains(objcon1.id))
                    {
                        setid.remove(objcon1.ReportsToId);
                    } else
                    {
                        lstobjconts.add(objcon1);
                        if(!mapcontact.containskey(objcon1.ReportsToId))
                        {
                            setnewids.add(objcon1.ReportsToId);
                            list<contact> lstcont = new list<contact>();
                            lstcont.add(objcon1);
                            mapcontact.put(objcon1.ReportsToId,lstcont);
                        }
                        else
                        {
                            mapcontact.get(objcon1.ReportsToId).add(objcon1);
                        }
                        setid.add(objcon1.id);
                        setid.remove(objcon1.ReportsToId);
                        j = j -1;
                    }
                }
            }
        }
        for(Contact con : contactList)
        {
            String contactfirstname ='';
            String contactlastname ='';
            String contactemail ='';
            String contactphone='';
           
            if(con.FirstName!=null)
            {
                contactfirstname = con.FirstName;
            }
            if(con.LastName!=null)
            {
                contactlastname = con.LastName;
            }
            if(con.Status1__c!=null)
            {
                contactemail = con.Status1__c;
            }
            if(con.Role__c!=null)
            {
                contactphone = String.valueOf(con.Role__c);
            }
            BindNodes currentContact = getNode(currentAccountNodeIcon,currentAccBorderColorMain,currentAccBorderColorNodeImage,currentAccBorderColorconnector,currentContactbgColor,bindNodeImage);
           
            currentContact.nodeId = 'O-'+String.valueOf(i);
            currentContact.parentNodeId='O-1';
            currentContact.template ='<div>'+contactemail+'\n<div align="center" style=\" font-size:20px;\n font-weight:bold;\n\"><a target=\"_blank\" href=\"'+ baseUrl + con.Id + '/view\">'+contactfirstname+' '+contactlastname+'</a></div>\n<div align="center" style=\" margin-top:20px;\n font-size:20px;\n font-weight:bold;\n\">'+contactphone+' </div>\n</div>';
            BindNodesList.add(currentContact);
            if(mapcontact.containskey(con.id))
            {
                integer count = i+1;
                for(id contid: setnewids)
                {
                    if(contid == con.id)
                    {
                        for(contact cont1 : mapcontact.get(contid))
                        {
                            String contactfirstname1 ='';
                            String contactlastname1 ='';
                            String contactemail1 ='';
                            String contactphone1='';
                           
                            if(cont1.FirstName!=null)
                            {
                                contactfirstname1 = cont1.FirstName;
                            }
                            if(cont1.LastName!=null)
                            {
                                contactlastname1 = cont1.LastName;
                            }
                            if(cont1.Status1__c!=null)
                            {
                                contactemail1 = cont1.Status1__c;
                            }
                            if(cont1.Role__c!=null)
                            {
                                contactphone1 = String.valueOf(cont1.Role__c);
                            }
                            if(cont1.id!=null)
                            {
                                con.id = cont1.id;
                            }
                            BindNodes currentContact1 = getNode(currentAccountNodeIcon,currentAccBorderColorMain,currentAccBorderColorNodeImage,currentAccBorderColorconnector,currentContactbgColor,bindNodeImage);
                           
                            currentContact1.nodeId = 'O-'+String.valueOf(count);
                            currentContact1.parentNodeId='O-'+String.valueOf(count-1);
                            currentContact1.template ='<div>'+contactemail1+'\n<div align="center" style=\" font-size:20px;\n font-weight:bold;\n\"><a target=\"_blank\" href=\"'+ baseUrl + cont1.Id + '/view\">'+contactfirstname1+' '+contactlastname1+'</a></div>\n<div align="center" style=\" margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\">'+contactphone1+' </div>\n</div>';
                            BindNodesList.add(currentContact1);
                            count++;
                        }
                    setnewids.remove(contid);
                    }
                }
                i = count;
            }

            else
                  if(mapcontact.containskey(con.id))
            {
                integer count = i+1;
                for(id contid: setnewids)
                {
                    if(contid == con.id)
                    {
                        for(contact cont2 : mapcontact.get(contid))
                        {
                            String contactfirstname2 ='';
                            String contactlastname2 ='';
                            String contactemail2 ='';
                            String contactphone2 ='';
                           
                            if(cont2.FirstName!=null)
                            {
                                contactfirstname2 = cont2.FirstName;
                            }
                            if(cont2.LastName!=null)
                            {
                                contactlastname2 = cont2.LastName;
                            }
                            if(cont2.Status1__c!=null)
                            {
                                contactemail2 = cont2.Status1__c;
                            }
                            if(cont2.Role__c!=null)
                            {
                                contactphone2 = String.valueOf(cont2.Role__c);
                            }
                            if(cont2.id!=null)
                            {
                                con.id = cont2.id;
                            }
                            BindNodes currentContact2 = getNode(currentAccountNodeIcon,currentAccBorderColorMain,currentAccBorderColorNodeImage,currentAccBorderColorconnector,currentContactbgColor,bindNodeImage);
                           
                            currentContact2.nodeId = 'O-'+String.valueOf(count);
                            currentContact2.parentNodeId='O-'+String.valueOf(count-1);
                            currentContact2.template ='<div>'+contactemail2+'\n<div align="center" style=\" font-size:20px;\n font-weight:bold;\n\"><a target=\"_blank\" href=\"'+ baseUrl + cont2.Id + '/view\">'+contactfirstname2+' '+contactlastname2+'</a></div>\n<div align="center" style=\" margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\">'+contactphone2+' </div>\n</div>';
                            BindNodesList.add(currentContact2);
                            count++;
                        }
                    setnewids.remove(contid);
                    }
                }
                i = count;
            }

                
                
            {
               i++;
            }
        }
       
        return BindNodesList;
    }
    public static List<BindNodes> getBindNodesAccount(List<Account> AccountList)
    {
        List<BindNodes> BindNodesList = new List<BindNodes>();
   
        BindNodes.NodeIcon currentAccountNodeIcon = getNodeIcon();
   
        BindNodes.BorderColor currentAccBorderColorMain =getBorderColorMain();
       
        BindNodes.BorderColor currentAccBorderColorNodeImage = getBorderColorNodeImage();
       
        BindNodes.BorderColor currentAccBorderColorconnector = getBorderColorconnector();
           
        BindNodes.BorderColor currentAccbgColor = getAccountBGColor();
       
        BindNodes.NodeImage bindNodeImage = getNodeImage(currentAccBorderColorNodeImage);
   
        BindNodes.BorderColor currentContactbgColor = getContactBGColor();
       
        Integer i = 2;
        String baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
        baseUrl = baseUrl + '/lightning/r/Account/';
        system.debug('===> baseUrl '+ baseUrl);
        for(Account currentAccountData: AccountList)
        {
            String accountName='';
            if(currentAccountData.Name!=null)
            {
                accountName = currentAccountData.name;
            }
            String accountPhone='';
            if(currentAccountData.Phone!=null)
            {
                accountPhone = String.valueOf(currentAccountData.Phone);
            }
            BindNodes currentAccount = getNode(currentAccountNodeIcon,currentAccBorderColorMain,currentAccBorderColorNodeImage,currentAccBorderColorconnector,currentContactbgColor,bindNodeImage);
            currentAccount.nodeId = 'O-'+String.valueOf(i);
            currentAccount.parentNodeId='O-1';
            currentAccount.template ='<div align="center">\n<div align="center" style=\" margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\"><a target=\"_blank\" href=\"'+ baseUrl + currentAccountData.Id + '/view\">'+accountName+'</a></div>\n<div align="center" style=\" margin-top:10px;\n font-size:20px;\n font-weight:bold;\n\">'+accountPhone+' </div>\n</div>';
            BindNodesList.add(currentAccount);
            i++;
        }
        return BindNodesList;
    }
}
-----------------------------------------------------------------------------------------------------------
Subclass for above class

public class BindNodes {
    public BindNodes()
    {
    }

    public class NodeImage {
        public NodeImage()
        {
        }
        public String url {get;set;} 
        public Integer width {get;set;} 
        public Integer height {get;set;} 
        public Integer centerTopDistance {get;set;} 
        public Integer centerLeftDistance {get;set;} 
        public String cornerShape {get;set;} 
        public Boolean shadow {get;set;} 
        public Integer borderWidth {get;set;} 
        public BorderColor borderColor {get;set;} 

        public NodeImage(JSONParser parser) {
            while (parser.nextToken() != System.JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
                        if (text == 'url') {
                            url = parser.getText();
                        } else if (text == 'width') {
                            width = parser.getIntegerValue();
                        } else if (text == 'height') {
                            height = parser.getIntegerValue();
                        } else if (text == 'centerTopDistance') {
                            centerTopDistance = parser.getIntegerValue();
                        } else if (text == 'centerLeftDistance') {
                            centerLeftDistance = parser.getIntegerValue();
                        } else if (text == 'cornerShape') {
                            cornerShape = parser.getText();
                        } else if (text == 'shadow') {
                            shadow = parser.getBooleanValue();
                        } else if (text == 'borderWidth') {
                            borderWidth = parser.getIntegerValue();
                        } else if (text == 'borderColor') {
                            borderColor = new BorderColor(parser);
                        } else {
                            System.debug(LoggingLevel.WARN, 'NodeImage consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }
    
    public String nodeId {get;set;} 
    public String parentNodeId {get;set;} 
    public Integer width {get;set;} 
    public Integer height {get;set;} 
    public Integer borderWidth {get;set;} 
    public Integer borderRadius {get;set;} 
    public BorderColor borderColor {get;set;} 
    public BorderColor backgroundColor {get;set;} 
    public NodeImage nodeImage {get;set;} 
    public NodeIcon nodeIcon {get;set;} 
    public String template {get;set;} 
    public BorderColor connectorLineColor {get;set;} 
    public Integer connectorLineWidth {get;set;} 
    public String dashArray {get;set;} 
    public Boolean expanded {get;set;} 
    public Integer directSubordinates {get;set;} 
    public Integer totalSubordinates {get;set;} 

    public BindNodes(JSONParser parser) {
        while (parser.nextToken() != System.JSONToken.END_OBJECT) {
            if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                String text = parser.getText();
                if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
                    if (text == 'nodeId') {
                        nodeId = parser.getText();
                    } else if (text == 'parentNodeId') {
                        parentNodeId = parser.getText();
                    } else if (text == 'width') {
                        width = parser.getIntegerValue();
                    } else if (text == 'height') {
                        height = parser.getIntegerValue();
                    } else if (text == 'borderWidth') {
                        borderWidth = parser.getIntegerValue();
                    } else if (text == 'borderRadius') {
                        borderRadius = parser.getIntegerValue();
                    } else if (text == 'borderColor') {
                        borderColor = new BorderColor(parser);
                    } else if (text == 'backgroundColor') {
                        backgroundColor = new BorderColor(parser);
                    } else if (text == 'nodeImage') {
                        nodeImage = new NodeImage(parser);
                    } else if (text == 'nodeIcon') {
                        nodeIcon = new NodeIcon(parser);
                    } else if (text == 'template') {
                        template = parser.getText();
                    } else if (text == 'connectorLineColor') {
                        connectorLineColor = new BorderColor(parser);
                    } else if (text == 'connectorLineWidth') {
                        connectorLineWidth = parser.getIntegerValue();
                    } else if (text == 'dashArray') {
                        dashArray = parser.getText();
                    } else if (text == 'expanded') {
                        expanded = parser.getBooleanValue();
                    } else if (text == 'directSubordinates') {
                        directSubordinates = parser.getIntegerValue();
                    } else if (text == 'totalSubordinates') {
                        totalSubordinates = parser.getIntegerValue();
                    } else {
                        System.debug(LoggingLevel.WARN, 'BindNodes consuming unrecognized property: '+text);
                        consumeObject(parser);
                    }
                }
            }
        }
    }
    
    public class BorderColor {
        public BorderColor()
        {
        }
        public Integer red {get;set;} 
        public Integer green {get;set;} 
        public Integer blue {get;set;} 
        public Integer alpha {get;set;} 

        public BorderColor(JSONParser parser) {
            while (parser.nextToken() != System.JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
                        if (text == 'red') {
                            red = parser.getIntegerValue();
                        } else if (text == 'green') {
                            green = parser.getIntegerValue();
                        } else if (text == 'blue') {
                            blue = parser.getIntegerValue();
                        } else if (text == 'alpha') {
                            alpha = parser.getIntegerValue();
                        } else {
                            System.debug(LoggingLevel.WARN, 'BorderColor consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }
    
    public class NodeIcon {
        public NodeIcon()
        {
        }
        public String icon {get;set;} 
        public Integer size {get;set;} 

        public NodeIcon(JSONParser parser) {
            while (parser.nextToken() != System.JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
                        if (text == 'icon') {
                            icon = parser.getText();
                        } else if (text == 'size') {
                            size = parser.getIntegerValue();
                        } else {
                            System.debug(LoggingLevel.WARN, 'NodeIcon consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }
    
    
    public static List<BindNodes> parse(String json) {
        System.JSONParser parser = System.JSON.createParser(json);
        return arrayOfBindNodes(parser);
    }
    
    public static void consumeObject(System.JSONParser parser) {
        Integer depth = 0;
        do {
            System.JSONToken curr = parser.getCurrentToken();
            if (curr == System.JSONToken.START_OBJECT || 
                curr == System.JSONToken.START_ARRAY) {
                depth++;
            } else if (curr == System.JSONToken.END_OBJECT ||
                curr == System.JSONToken.END_ARRAY) {
                depth--;
            }
        } while (depth > 0 && parser.nextToken() != null);
    }
    
    public static List<BindNodes> arrayOfBindNodes(System.JSONParser p) {
        List<BindNodes> res = new List<BindNodes>();
        if (p.getCurrentToken() == null) p.nextToken();
        while (p.nextToken() != System.JSONToken.END_ARRAY) {
            res.add(new BindNodes(p));
        }
        return res;
    }
}

 
AbhishekAbhishek (Salesforce Developers) 
Besides lightning:tree component there is lightning:treeGrid one. There are small differences in implementation but I think that treeGrid just looks better.

Component

<aura:component>
<aura:handler name="init" value="{!this}" action="{!c.init}" />
<aura:attribute name="gridColumns" type="List" />
<aura:attribute name="gridData" type="Object" />
<aura:attribute name="gridExpandedRows" type="Object" />
<lightning:treeGrid
    columns="{! v.gridColumns }"
    data="{! v.gridData }"
    expandedRows="{! v.gridExpandedRows }"
    keyField="name"
    aura:id="mytree"
/>



Controller

({
init: function (cmp) {
    var columns = [
        {
            type: 'text',
            fieldName: 'accountName',
            label: 'Account Name'
        },
        {
            type: 'number',
            fieldName: 'employees',
            label: 'Employees'
        },
        {
            type: 'phone',
            fieldName: 'phone',
            label: 'Phone Number'
        },
        {
            type: 'url',
            fieldName: 'accountOwner',
            label: 'Account Owner',
            typeAttributes: {
                label: { fieldName: 'accountOwnerName' }
            }
        }
    ];
    cmp.set('v.gridColumns', columns);
    var nestedData = [
        {
            "name": "123555",
            "accountName": "Rewis Inc",
            "employees": 3100,
            "phone": "837-555-1212",
            "accountOwner": "http://sfdc.co/jane-doe",
            "accountOwnerName": "Jane Doe"
        },
        {
            "name": "123556",
            "accountName": "Acme Corporation",
            "employees": 10000,
            "phone": "837-555-1212",
            "accountOwner": "http://sfdc.co/john-doe",
            "accountOwnerName": "John Doe",
            "_children": [
                {
                    "name": "123556-A",
                    "accountName": "Acme Corporation (Bay Area)",
                    "employees": 3000,
                    "phone": "837-555-1212",
                    "accountOwner": "http://sfdc.co/john-doe",
                    "accountOwnerName": "John Doe",
                    "_children": [
                        {
                            "name": "123556-A-A",
                            "accountName": "Acme Corporation (Oakland)",
                            "employees": 745,
                            "phone": "837-555-1212",
                            "accountOwner": "http://sfdc.co/john-doe",
                            "accountOwnerName": "John Doe"
                        },
                        {
                            "name": "123556-A-B",
                            "accountName": "Acme Corporation (San Francisco)",
                            "employees": 578,
                            "phone": "837-555-1212",
                            "accountOwner": "http://sfdc.co/jane-doe",
                            "accountOwnerName": "Jane Doe"
                        }
                    ]
                }
            ]
        },
    ];
    cmp.set('v.gridData', nestedData);
    var expandedRows = ["123556"];
    cmp.set('v.gridExpandedRows', expandedRows);
}
})
Additionally if you want to create custom hierarchy of how many levels you want I used this algorithm to correctly place data in the structure:

 getNestedChildren :  function (models, parentId) {
    const nestedTreeStructure = [];
    const length = models.length;

    for (let i = 0; i < length; i++) {
        const model = models[i];

        if (model.parent == parentId) {
            const _children = this.getNestedChildren(models, model.id);

            if (_children.length > 0) {
                model._children = _children;
            }

            nestedTreeStructure.push(model);
        }
    }

    return nestedTreeStructure;
}



Where model is a flat array of parents and kids and parentId is id which parents have (in my case it was just null).

References:

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

https://stackoverflow.com/questions/444296/how-to-efficiently-build-a-tree-from-a-flat-structure

You have to make some changes based on your requirement.

I hope you find the above information is helpful. If it does, please mark as Best Answer to help others too.

Thanks.
Alain CabonAlain Cabon
The problem with a large graph in SVG is the "search" and the "export as an image" buttons that are often missing by default.

Will Chen has forked the David Bumbeishvili's project and added the search. 

I also found the export as image for D3 but I need to merge the new features in my own fork.

David Bumbeishvili's version is easy to configure while Will Chen has hard coded many things but interesting new features.

https://bl.ocks.org/willzjc/a11626a31c65ba5d319fcf8b8870f281