Sunday, 5 June 2011

Show Hierarchy in Visualforce Page

Hi,

I saw this question regularly in developer community how to show items in a hierarchy in VFP like this.
Parent
   Child 1
       Grand Child1
   Child 2
       Grand Child2

Now here is an Example :
I created a New Object Hierarchy
Added two fields in it :
1) AccountId : To save reference to Account Record
2)Parent Hierarchy : To save the Parent Hierarchy record

I created a Account : Test Hierarchy
And 5 Records for Hierarchy Object for this account record
 Parent1 : No parent hierarchy
 Child 1 : Parent Hierarchy =  Parent1
 Child 2 : Parent Hierarchy =  Parent1

 Grand Child 1 : Parent Hierarchy =  Child1
 Grand Child 2 : Parent Hierarchy =  Child2


Now our Aim is to show them in this way

Parent1
    Child1
          GrandChild11
    Child2
          GrandChild12

Apex Controller For this

//Create Hierarchy
public class hierarchy{

    //List of items to be displayed in hierarchy
    public List<hierarchyItem> hierarchyItemList {get;set;}
    
    //map of all  hierarchy records related to for a account for which we are showing hierarchy
    private Map<Id , Hierarchy__c> mapHierarchy = new Map<Id , Hierarchy__c>();
    
    //Hierarchy Index, used to determine spaces before the name starts
    private static Integer hirarchyIndex = 0;
    
    //name of account for which hierarchy is created
    public String AccountName {get;set;}
    
    public hierarchy()
    {
        if(ApexPages.currentPage().getParameters().get('accountid') != null)
        {
            ID AccountID = ApexPages.currentPage().getParameters().get('accountid');
           
            AccountName = [Select Name From Account where id =: AccountID].Name;
            //Get all hierarchy records related to account
            mapHierarchy = new Map<Id , Hierarchy__c>([Select Name , Parent_Hierarchy__c  From Hierarchy__c Where AccountId__c =: AccountID]);
            
           
            
            List<Hierarchy> listParentHierarchy = new List<Hierarchy>();
            hierarchyItemList = new List<hierarchyItem>();
            
            for(Hierarchy__c h : mapHierarchy.values())
                {
                    if(h.Parent_Hierarchy__c  == null)
                    {
                        hierarchyItemList.add(new hierarchyItem( h.Name , 0));
                        mapHierarchy.remove(h.id);
                        hierarchyItemList = getChildHierarchy(h.id , hierarchyItemList);
                    }
                    
                }
        }
    }

    //Method to get child records
    private List<hierarchyItem> getChildHierarchy(Id parentId , List<hierarchyItem> currentHierarchyItemList)
    {
        hirarchyIndex = hirarchyIndex + 1;
        for(Hierarchy__c h : mapHierarchy.values())
            {
                if(h.Parent_Hierarchy__c == parentId)
                    {
                        hierarchyItemList.add(new hierarchyItem( h.Name , hirarchyIndex));
                        mapHierarchy.remove(h.id);
                        //Get child records of child
                        hierarchyItemList = getChildHierarchy(h.id , hierarchyItemList);
                    }
                
            }
        hirarchyIndex = hirarchyIndex - 1;    
        return currentHierarchyItemList;    
    }    
    
    //Inner class for maintaing hierarchy items
    public class hierarchyItem{
        
        public String itemValue{get;set;} 
        public String hirarchyIndexNo{get;set;}
        public hierarchyItem(String itemValue , Integer hirarchyIndexNo)
            {
                String spaceCount = '';
                for(integer i = 0 ; i < hirarchyIndexNo ; i++)
                    spaceCount = spaceCount  + '&nbsp;&nbsp;';
                    
                this.itemValue = spaceCount + itemValue;
            }
    }

}


<apex:page controller="hierarchy">
  <apex:form>
     <apex:pageBlock>
         <apex:pageblockSection columns="1" title="Hierarchy For {!AccountName}">
             <apex:repeat value="{!hierarchyItemList}" var="item">
                <apex:pageBlockSectionItem>
                    <apex:outputLabel value="{!item.itemValue}" escape="false"/>
                </apex:pageBlockSectionItem>
             </apex:repeat>
         </apex:pageblockSection>
     </apex:pageBlock>
  </apex:form>
 </apex:page>

In VFP I have used escape="false" in the outPutLabel to allow html rendering in our case &npsp; to show blank space. We can easily achieve this using it without it with use of Apex:Variable and calculate space with help of it.

Now give URL to your VFP in address bar and pass account id in query string
like this

/apex/YourPageName?accountid=00190000007EKOG

View The result



In above Child2 has come first as Hierarchy records are coming from SOQL are DESC order of Last Modified date.

Regards

4 comments:

  1. This worked great for my use case! Thanks for sharing this.

    3 expansion questions:

    1) My case is Countries, States and Cities as Parent, Child, GrandChild Respectively. I would like to have Data Display by States Alphabetically and then City Alphabetically. How can I achieve this? I tried
    mapHierarchy = new Map([Select Name , Parent_Hierarchy__c From Service_Area__c ORDER BY NAME ASC]); but it did not change anything.

    2) I need my data to be used as links, and the escape attribute is not supported in the . How would I use Apex:Variable and calculate space with help of it?

    3) If I want to display the number of cities in 4 columns, do you have any thoughts on an easy solution to achieve this? Lets say I displayed each country list in a separate pageblocksection and I distributed the list of cities over 4 columns. Any suggestions

    ReplyDelete
  2. This can be achieved without using another object to keep track of your hierarchy

    ReplyDelete
  3. Not displaying any hierarchy in VFP.

    ReplyDelete
  4. yes. not working

    ReplyDelete

Tweet