1

Good Old question but unable to figure out a easy way. can some one please guide me if anyone has faced this. I am working on dislaying a complex tree-branch-leaf structure.All the Tree-Branch-Leaf records will be inserted in same object with different record type. Please see the screenshot of what i am trying to build. enter image description here

Can someone please guide me how can i Loop each record and create a Nested structure or Map so that a proper Json can be made. Since its a self look up to same object, it is becoming difficult

1 Answer 1

5

This is one of those things best solved with a Visualforce Component, and a TreeNode class; this fixes the problem of how to deal with (potentially) infinite recursion in a sensible manner.

public class TreeNode {
  public TreeNode parent { get; set; }
  public Object value { get; set; } // Holds the value in this node
  public TreeNode[] children { get; set; } // Holds the value of child nodes
  public TreeNode(TreeNode p, Object v) {
    parent = p;
    value = v;
    children = value;
  }
}

<apex:component>
  <apex:attribute name="node" type="TreeNode[]" />
  <div>
  {!node.value}
  <div style="padding-left: 1em">
  <apex:repeat value="{!node.children}" var="child">
    <c:treeNode node="{!child}" />
  </apex:repeat>
  </div>
  </div>
</apex:repeat>

Your main page's controller will expose this value like this:

public class PageController {
  public TreeNode root { get; set; }
  ...
}

At this point, all you need to do is to populate the list of nodes.

To populate this efficiently, you need a Map. The general algorithm looks like this:

Map<Id, TreeNode> nodes = new Map<Id, TreeNode>();
// Populate parents
nodes.put(null, new TreeNode(null, null));
for(Object record: recordList) {
  nodes.put(record.Id, new TreeNode(null, record));
}
// Link parents
for(Object record: recordList) {
  if(record.parentid != null) {
    nodes.get(record.id).parent = nodes.get(record.parentid);
  }
}
// Populate children
for(Object record: recordList) {
  nodes.get(record.parentid).children(nodes.get(record.id));
}
root = nodes.get(null);
nodes = null; // the map is no longer needed.

The final output will be a single root node (identified by the Id null), that will contain a nested tree of all the items.

Note that this is a very, very rough draft that will need some manipulation for concrete data types, etc.

Note that this TreeNode implementation also includes a link to the parent node; this allows you to calculate the IdChain__c:

for(TreeNode node: nodes.values()) {
  String[] idChain = new String[] { '' }; // Temporary place holder
  TreeNode temp = node;
  while(temp != null) {
    idChain.add(0, temp.value.Id); // insert in first position, shifts all others up one
    temp = temp.parent;
  }
  idChain.remove(idChain.size()-1); // Remove temp place holder
  node.value.idChain__c = String.join(idChain, '.');

I realize this isn't necessarily a full answer, but it has all the essential parts that you'll need to complete your task.

4
  • thanks but i didn't get the Populate children part. So you are saying we need to iterate through each branch level records or all set of records? @sfdcfox Commented Feb 28, 2018 at 13:50
  • @chandrakanth The full set of records; the map takes care of filling out your branches for you. I actually have a demo of this (in Lightning) that is designed nearly identical as to how it's described here. I'll set up a gist for you.
    – sfdcfox
    Commented Feb 28, 2018 at 15:27
  • 1
    @chandrakanth See this gist for a demo in Lightning; the logic would be very similar in Visualforce; you need a treeNode component, it would have the ability to accept a tree node, it would show the name, then iterate over the list of children, etc.
    – sfdcfox
    Commented Feb 28, 2018 at 15:42
  • Thanks for gist. I got the whole idea. However i am getting the following error. Since there is a character limit on the comment section i had to create a new post. Please see - link @sfdcfox Commented Mar 1, 2018 at 6:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .