+ Start a Discussion
Laxman Vattam 26Laxman Vattam 26 

showing related records in hierarchy in visualforce page

I want to show 5 different custom object records in hierarchial way in Visualforce page. All these 5 objects are linked thru parent child relationships
CObject1
      CObject 2
             CObject3
                   CObject4
                         CObject5

As you see, each object is child to another. Now I want to display first record of CObject1 then followed by all its children and then second record of CObject1 followed by all 4 children and so on. How can I achieve it?



 
Alain CabonAlain Cabon
Hi,

I am currently learning the dynamic components in Apex/VFP because I will have to use them for this kind of problems precisely.

A first code and result could be like that: 
  1. for this first version, the apex:dynamicComponent is not needed at all but it is my draft code and the next version should be much better
  2. I read all the values of CObject1, CObject1 and CObject3 at the beginning (theoretical and not real world).

User-added image
 
<apex:page standardController="Contact" extensions="DynamicHierarchyComponent">  
    <apex:pageblock >	
        <apex:dynamicComponent componentValue="{!Hierarchy}"/>				
    </apex:pageblock>	
</apex:page>
 
public class DynamicHierarchyComponent {
    public DynamicHierarchyComponent(ApexPages.StandardController con) { }
    
    public List<String> items {get;set;}
    
    static Map<String,Map<Id,List<sObject>>> allvalues;
    
    static  Map<Id,List<sObject>> parentmap(String object_name){
        List<sObject> c2 =  Database.query('select id,name,parent__c from ' + object_name + ' order by name');    
        Map<Id,List<sObject>> m2 = new  Map<Id,List<sObject>>();
        String parentid = '';
        for (sObject o2:c2) {
            parentid = null;
            if (object_name == 'CObject_2__c') {
                parentid = ((CObject_2__c) o2).parent__c;
            } 
            if (object_name == 'CObject_3__c') {
                parentid = ((CObject_3__c) o2).parent__c;
            } 
            if (parentid == null) continue;
            if (m2.containsKey(parentid)) {
                ((List<sObject>) m2.get(parentid)).add(o2);
            } else {
                m2.put(parentid, new List<sObject>{o2});
            }
        }
        return m2;
    }
    
    public  Component.Apex.PageBlockTable getHierarchy() {
        
        Map<Id,CObject_1__c> c1 = new  Map<Id,CObject_1__c>([select id,name from CObject_1__c order by name]);      
        allvalues = new  Map<String,Map<Id,List<sObject>>>(); 
        allvalues.put('CObject_2__c',parentmap('CObject_2__c'));
        allvalues.put('CObject_3__c',parentmap('CObject_3__c'));
        
        items = new List<String>();
        Component.Apex.PageBlockTable myTable = new  Component.Apex.PageBlockTable(var='item');
        myTable.expressions.value = '{!items}';
        
        Component.Apex.column clm = new Component.Apex.column(headerValue= 'Name'); 
        myTable.childComponents.add( clm );
        Component.Apex.OutputText outText = new Component.Apex.OutputText( );			
        outText.expressions.value = '{!item}';			
        clm.childComponents.add( outText );		
        
        for (Id id1 :c1.keyset()) {
            CObject_1__c o1 = (CObject_1__c) c1.get(id1);
            items.add(o1.name);
            getNodes('CObject_2__c',o1.id);
        }            
        return myTable;
    }
    public void getNodes(String object_name,String parentid) {        
        String name = '';
        String id = '';        
        Map<Id,List<sObject>> map1 = (Map<Id,List<sObject>>) allvalues.get(object_name);      
        if (object_name == 'CObject_2__c') {
            if (map1.containsKey(parentid)) {
                List<CObject_2__c> lcob = (List<CObject_2__c>) map1.get(parentid);
                for (CObject_2__c cob:lcob) {
                    name = cob.name;
                    items.add('*** ' + name);
                    getNodes('CObject_3__c',cob.id);
                }
            }     
        } else
            if (object_name == 'CObject_3__c') {
                if (map1.containsKey(parentid)) {
                    List<CObject_3__c> lcob = (List<CObject_3__c>) map1.get(parentid);
                    for (CObject_3__c cob:lcob) {
                        name = cob.name;
                        items.add('****** ' + name);
                    }
                }   
            }      
    }
}

I will need this kind of hierarchical component too but all the parameters should be dynamic (objecs, columns, formats and so on).

This first version is the one you write by default when you are not an expert of  apex:dynamicComponent.

The next version should be much better.

Best regards
Alain
Laxman Vattam 26Laxman Vattam 26
Thanks Alain for posting sample code.

This initial code doesnt handle showing column headers for various objects in the hierarchy. Also, I dont see any easy way to show this hierachial data along with column headers with good UI experince. :(

I really appreciate your inputs
Alain CabonAlain Cabon
Hi,

For VFP with a static layout (not dynamic), I heavily use <apex:column breakBefore="true"​> for including a table into a column for my own tool I am building currently.
This is not dynamic but that works fine.
You "just" have to fill the map of data according the design of your VFP but that is not so complex.
<apex:pageblocktable >
     <apex:column breakBefore="true" colspan="5">
          <apex:pageblocktable >
              <apex:column>

'View Hierarchy' functionality to be available on custom objects:
https://success.salesforce.com/ideaView?id=08730000000BrHwAAK

Traversing through an Account’s Hierarchy in Apex: one object 
https://jdspaceit.wordpress.com/2016/01/13/traversing-through-an-accounts-hierarchy-in-apex/

Managing multiple multilevel account hierarchies efficiently in Apex: one object
https://sfbypeter.wordpress.com/2015/10/19/managing-multiple-multilevel-account-hierarchies-efficiently-in-apex/

Best regards
Alain