Skip to main content

Tree Structure for Self related records in salesforce

How to build a tree for the records which has self lookup?

Here I am taking a custom object called Category__c and created a self-lookup to it with the field FKParentCategory__c.

Controller:
public without sharing class categoryTreeController {
 
    List<Category__c> parentrecord;
    Map<Id, List<Category__c>> categoryMap{get;set;}
    public string treeJSON{get;set;}
    public string treeJSON2{get;set;}
    private string whereClause;
    public integer count{get;set;}
    public categoryTreeController ()
    {
        treeJSON='[';
        count=0;
        whereClause='';
     
        string pageName=ApexPages.currentPage().getParameters().get('pageName');
        if(pageName=='clientPage'){
            whereClause=' Display_for_end_users=true;
                }else if(pageName=='' || pageName==null){
                    whereClause= ' AvailableForAll__c = TRUE';
                }
     
        parentrecord=Database.query('select id, name from Category__c where FKParentCategory__c=null and '+ whereClause+
                                    ' ORDER BY name');
     
        categoryMap= getcategoryMap();
        for(Category__c serviceDeskRec: parentrecord){
         
            if(categoryMap.containsKey(serviceDeskRec.Id))
            {
                buildTreeJSON(serviceDeskRec, true);
            }
         
        }

        treeJSON= treeJSON.substring(0, treeJSON.lastIndexOf(','));
        treeJSON+=']';
     
    }
 
    public Map<Id, List<Category__c>> getcategoryMap()
    {
        Map<Id, List<Category__c>> categoryMap=new Map<Id, List<Category__c>>();    
        string query='select id,name,  (select name, id from Categories__r where '+whereClause+' order by name) from Category__c where '+
            whereClause +' order by name';
     
        for(Category__c CategoryRec:database.query(query))
         
        {
         
            if( CategoryRec.Categories__r!=NULL)
                count=count+CategoryRec.Categories__r.size();
            categoryMap.put(CategoryRec.Id, CategoryRec.Categories__r!=null?(List<Category__c>)CategoryRec.Categories__r:NULL);
         
        }
        return categoryMap;
     
    }
 
    public string buildTreeJSON(Category__c record, boolean parentRec)
    {
        Boolean hasChild= categoryMap.get(record.id)==null?false:true;
     
        if(parentRec)
            treeJSON= treeJSON+'{"id":"'+ record.Id +'","parent":' + '"#"' +  ',"text": '+'"'+record.Name+ '"},';
     
        if(categoryMap.get(record.id)!=NULL)
        {
            for(Category__c cats :categoryMap.get(record.id)){
                treeJSON= treeJSON+'{"id":"'+ cats.Id +'","parent":' + '"'+ record.Id+'"' +  ',"text": '+'"'+cats.Name+ '"},';
                buildTreeJSON(cats,false);
             
            }
         
        }
     
        return treeJSON;
     
    }
 
}

-----------------------------------------------------------------------------------
Visualforce Page:

<apex:page id="thePage" controller="categoryTreeController" showHeader="false">
    <apex:stylesheet value="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css"/>
 
    <apex:form >
     
        <div id="jstree"></div>
     
    </apex:form>
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
    <script>
 
    var j$=jQuery.noConflict();
 
    j$(function () { j$('#jstree').jstree( {
        "core":{
            "data":{!treeJSON}
         
        }  
     
    });
                    j$('#jstree').on('changed.jstree', function (e, data) {
                        var i, j;
                        for(i = 0, j = data.selected.length; i < j; i++) {
                         
                            if(data.instance.is_parent(data.selected[i])==false)
                            {
                                stampCategoryVals(data.instance.get_node(data.selected[i]).id, data.instance.get_node(data.selected[i]).text);
                             
                            }
                        }
                     
                    })
                 
                   });
 
    function stampCategoryVals(categoryId, categoryName)
    {
        var winMain=window.opener;
        if(null==winMain){
            winMain=window.parent.opener;
        }
     
        winMain.closeCategoryLookupPopup(categoryId,categoryName);
        winMain.categoryToggle();
     
    }
 
    </script>
</apex:page>

Comments

Popular posts from this blog

Track Field History for more than 20 fields - Salesforce

All of us would have come across a situation when we need to track more than 20 fields for an object in salesforce. We have raised this Idea around 8 years ago in the success community. But sill it has't implemented by salesforce. But for now, we can achieve it partially with the following workaround. Approach: This approach uses a custom Text field which stores values of multiple other individual fields. Then enabling field history tracking of this field would allow you to track changes for multiple sets of other individual fields. Thus even though remaining within the count limit 20, yet track changes of more than 20 fields. Let us in this example take “Account ”  object and apply the steps to track change in Account Name, Phone, Parent Account and Billing Address all together. Steps: Step 1:  Add a new custom field. Setup -> Customize -> Accounts -> Fields Create a new Text (255) field “ Track FieldHistory ” (Or give any other n...

Customize the columns in the Items to Approve section on home page

We can customize the items to approve section with the help of custom visualforce page. All you need to do is create the below page with your object and respected fields to be displayed and then add the page to a new home page component. Page: <apex:page controller="itemstoApprovecontroller" sidebar="false" showHeader="false">     <apex:form >         <apex:pageBlock title="Incidents/Service Request To Approve">             <apex:pageBlockTable value="{!items_to_approve}" var="item_to_approve">                 <apex:column headerValue="Action" width="160 px" >                                     <apex:commandLink target="_top" value="Reassign |" action="{!REASSIGNnavigation}" style="text-decoration:none;color: #015ba7;" styleClass="cactionLink">   ...

Kanban view for Lightning

Tired of list views? Looking for a dynamic views to show your cases or opportunities in all new way? Here we go,  Salesforce introduced Kanban views for us to have better visibility  of our cases/opportunities and their journey from opening to closure. A case kanban allows you to visually summarize all of the cases for your agents,  by status or priority. It's not only a board, but also a  drag and drop  tool that will help agents keep their cases moving towards resolution. Similarly an opportunity Kanban display opportunities from a particular sales path Let's take a closer look at what all we can do with Kanban Track a Deal with Path Display opportunities by Sales path Move an Opportunity to the Next Stage Take Action on Your Records