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
Sainath VenkatSainath Venkat 

apex and visualforce tree to show 4 levels

Hello Guys
I am working on one requirement of creating a tree that can show upto 4 levels, I have achieved for 2 levels but don't know how to proceed further here.
I created 3 objects
1) Action_Item__c
2) Test__c
3)Test_Result__c

Test_Result__c is having lookup to Test__c and Test__c is having lookup to action item, so in tree for action item I want to show all related test__c records. I did for action item which is having self lookup. Can anyone help me out in this please. My code is below.

Apex Class:
public class accconhierarchy {
    Private list<Action_Item__c> acc;
    
    public List<accountWrap> accountList { get; set; }
    public accconhierarchy (){
        List<contactWrap> cw;
        accountList = new List<accountWrap>();
        acc = [select id,name,Priority__c,Hours_act__c,Due_Date__c,(select id,name,Priority__c,Hours_act__c,Due_Date__c from Related_Action_Items__r) from Action_Item__c limit 500];
        for(Action_Item__c a:acc){
            cw = new list<contactWrap>();
            For(Action_Item__c co : a.Related_Action_Items__r){
               cw.add(new contactWrap(co));
            }
            accountList.add(new accountWrap(a,false,cw));
        }
    }
    
    public class accountWrap{
        public Action_Item__c oAccount{get;set;}
        public boolean isSelected{get;set;}
        public List<contactWrap> contactset{get;set;}
        public accountWrap(Action_Item__c a,boolean b, List<contactWrap> c){
            oAccount=a;
            isSelected=b;
            contactset =c;            
        }
    }
    
    public class contactWrap{
        public Action_Item__c oContact{get;set;}
        public boolean isSelected{get;set;}        
        public contactWrap(Action_Item__c a){
            oContact=a;
            isSelected=false;                       
        }
    }
    
}
VF Page:
 
<apex:page controller="accconhierarchy">
  <apex:form >
      <apex:pageBlock >
      <style type="text/css">
        .showContacts {
            background: transparent url('/img/alohaSkin/twisty_sprite.png') 0 0 no-repeat;
        }
        .hideContacts {
            background: transparent url('/img/alohaSkin/twisty_sprite.png') 0 -11px no-repeat;
        }
    </style>
                  <apex:outputPanel layout="none"
                        rendered="{!accountList.size!=0}">
                        <table id="tableAccount" class="list" border="0" cellpadding="0" cellspacing="0">
                            <thead>
                                <tr class="headerRow">
                                    <th class="actionColumn">Action</th>
                                    <th>Action Item Name</th>
                                    <th>Due Date</th>
                                    <th>Hours Actual</th>
                                    <th>Priority</th>
                                </tr>
                            </thead>
                            <tbody>
                            <apex:repeat id="repeatAccount"
                                value="{!accountList}"
                                var="item">
                                <apex:variable var="acc" value="{!item.oAccount}" />   
                                <tr id="{!$Component.repeatAccount}:account" class="dataRow">
                                    <td class="actionColumn">
                                        <apex:inputCheckbox id="selectAccountRow"
                                            value="{!item.IsSelected}"
                                            onclick="javascript:toggleSelectAll(this, '{!$Component.repeatAccount}');"/>
                                    </td>
                                    <td class="dataCell">
                                        <apex:outputLink id="linkShowHide" value="javascript:toggleContactRow('{!$Component.repeatAccount}')">
                                            <img id="{!$Component.repeatAccount}:Img" src="/s.gif" class="showContacts" border="0" height="11px" width="11px" style="padding-right: 4px;"/>
                                            <apex:outputField value="{!acc.Name}" />
                                        </apex:outputLink>
                                    </td>
                                    <td class="dataCell"><apex:outputField value="{!acc.Due_Date__c}" /></td>
                                    <td class="dataCell"><apex:outputField value="{!acc.Hours_act__c}" /></td>
                                    <td class="dataCell"><apex:outputField value="{!acc.Priority__c}" /></td>
                                </tr>

                                <tr id="{!$Component.repeatAccount}:Contact" class="dataRow" style="display:none;">
                                    <td colspan="100" style="padding:10px; padding-left: 45px;">
                                        <h3>Child Action Items</h3>
                                        <br/>                                        
                                        <apex:outputPanel layout="none">                                            
                                            <table id="tableAccountContacts" class="list" border="0" cellpadding="0" cellspacing="0">
                                                <thead>
                                                    <tr class="headerRow">
                                                        <th class="actionColumn">Action</th>
                                                        <th>Name</th>
                                                        <th>Hours Actual</th>
                                                        <th>Priority</th>
                                                    </tr>
                                                </thead>
                                                <tbody>
                                                <apex:repeat id="repeatAccountContacts"
                                                    value="{!item.contactSet}"
                                                    var="subitem">
                                                    <apex:variable value="{!subitem.oContact}" var="con" />
                                                    <tr class="dataRow">
                                                        <td class="actionColumn"><apex:inputCheckbox id="selectContactRow" styleclass="ContactCheckbox" value="{!subitem.IsSelected}"/></td>
                                                        <td class="dataCell"><apex:outputField value="{!con.Name}" /></td>
                                                        <td class="dataCell"><apex:outputField value="{!con.Hours_act__c}"/></td>
                                                        <td class="dataCell"><apex:outputField value="{!con.Priority__c}" /></td>                                                        
                                                    </tr>
                                                </apex:repeat>
                                                </tbody>
                                            </table>
                                        </apex:outputPanel>
                                    </td>
                                </tr>
                            </apex:repeat>
                            </tbody>
                        </table>
                    </apex:outputPanel>
 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
 <script>
        jQuery.noConflict();
        function toggleContactRow(rowId) {
            try {
                var AccountImg = jQuery(document.getElementById(rowId + ":Img"));
                var ContactsRow = jQuery(document.getElementById(rowId + ":Contact"));
                if (AccountImg.hasClass("hideContacts")) {
                    AccountImg.attr("class", "showContacts");
                    ContactsRow.hide();
                }
                else {
                    AccountImg.attr("class", "hideContacts");
                    ContactsRow.show();
                }
            }
            catch (e) { alert(e); }
        }  

        function toggleSelectAll(elCheckbox, rowId) {
            try {
                var SelectAll = jQuery(elCheckbox);
                var ContactsRow = jQuery(document.getElementById(rowId + ":Contact"));
                ContactsRow.find(".ContactCheckbox").each(function() {
                    jQuery(this).prop("checked", SelectAll.is(":checked"));
                });
            }
            catch (e) { alert(e); }
        }

    </script> 
    </apex:pageBlock>
  </apex:form>
</apex:page>


 
Khan AnasKhan Anas (Salesforce Developers) 
Hi Sainath,

I trust you are doing very well.

Please refer to the below blogs which has sample code which might help you with the above requirement. Kindly try to implement according to your requirement.

http://salesforceglobe4u.blogspot.com/2015/12/tree-structure-in-visualforce-pageupto.html

http://www.forcetree.com/2011/04/tree-view-in-visualforce-page.html

http://forceschool.blogspot.com/2011/06/show-hierarchy-in-visualforce-page.html

http://www.infallibletechie.com/2012/11/tree-view-in-visualforce-page.html

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

http://salesforceblogger.blogspot.com/2012/03/hierarchy-in-visualforce.html

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Thanks and Regards,
Khan Anas
lkatneylkatney

Hi Sainath,

I worked on something similar and want to share my solution. I worked on the Lightning Web Component (LWC) to achieve this tree structure. It is just 5 lines for code in HTML and you don't need this much code on your page however Apex is a little bit heavy.

In my solution, I am displaying 360 views for all accounts with all their opportunities, contacts & cases. This uses recursion to go to any number of levels possible. Please bear governor limits in mind while designing your solution.

Here are the links:
https://blog.lkatney.com/2019/05/22/dynamic-tree-structure-with-lwc/
https://playground.lkatney.com/play/dynamic-tree-structure-with-lwc

Just replace queries with your object queries and it should work. Hope this helps you!

Thanks