+ Start a Discussion
Qin LuQin Lu 

Dynamically render sections based on types

I have a custom object A, it has a type field
if I have the following records in A
Name.       Type
aaa.           Checking
bbb.            Checking
ccc.            Investment
ddd.            Saving

I want to build a page showing 3 sections 
Checking
aaa
bbb

Investment
ccc

Saving
ddd

it is possible that the data doesn't contain Saving type of record, then I don't want Saving section showing up. It is possible that new types are added, for example, we have another Type Retirement added. 
eee. Retirement
then I want to have another section rendered. Basically I can't hard code the name of the Type because it can change/expand, and I can't put fixed number of sections in page because it could change based on Tyes. 
Is there any way to achieve this?


Best Answer chosen by Qin Lu
kiranmutturukiranmutturu
One of the best solution is to prepare a custom settings like section name and list of fields (You shoould give the API names to be associated to the section) and finally generate a dynamic section through Apex code by using the custom settings object and display them in VF.

Advantage of this is when ever you want to add a new type you just need add the related record to the custom setting object. No change in the code base/.

Some thing like this

public Component.Apex.OutputPanel getproductSpecificInformation() 
    {
    	Component.Apex.OutputPanel productSpecificInformation = new Component.Apex.OutputPanel();
    	
    	List<SobjectSortByNumberWrapper> sortedProductServiceMapping = new List<SobjectSortByNumberWrapper>();
		
		for (ProductServiceMapping__c psm : ProductServiceMapping__c.getAll().values())
		{
			sortedProductServiceMapping.add(new SobjectSortByNumberWrapper(psm, 'SectionOrder__c'));
		}
		
		sortedProductServiceMapping.sort();
		
		for (SobjectSortByNumberWrapper sList : sortedProductServiceMapping)
		{
			ProductServiceMapping__c psm = (ProductServiceMapping__c) sList.mainObj;

			Component.Apex.PageBlockSection pageBlockSec = new Component.Apex.PageBlockSection(title=psm.Section__c,collapsible=false,columns=2);
				
			Component.Apex.OutputField theNameField = new Component.Apex.OutputField();

			theNameField.expressions.value = '{!productService.' + s +'}';

			pageBlockSec.childComponents.add(theNameField);
			
			productSpecificInformation.childComponents.add(pageBlockSec);
	            
	    }
		
		return productSpecificInformation;
    }

and call the method from VF page some thing like this

<apex:outputpanel id="prodSpecInfo">
                <apex:dynamicComponent componentValue="{!productSpecificInformation}" />
            </apex:outputpanel>
This is just a sample that I used in my business scenario....






All Answers

Ramu_SFDCRamu_SFDC
Hi, basically to render certain sections we usually determine the sections(Like output panels, pageblock sections etc..,) based on their ID value. In the current case it is possible to fetch the type values dynamically using describe calls. However, you still have to hardcode the section ID names to represent those based on the type.

The below post explains how you can hide a section based on the picklist value change

https://success.salesforce.com/answers?id=90630000000hTaaAAE

Yet another example https://developer.salesforce.com/forums/ForumsMain?id=906F000000097h9IAA

Hope this helps !
kiranmutturukiranmutturu
One of the best solution is to prepare a custom settings like section name and list of fields (You shoould give the API names to be associated to the section) and finally generate a dynamic section through Apex code by using the custom settings object and display them in VF.

Advantage of this is when ever you want to add a new type you just need add the related record to the custom setting object. No change in the code base/.

Some thing like this

public Component.Apex.OutputPanel getproductSpecificInformation() 
    {
    	Component.Apex.OutputPanel productSpecificInformation = new Component.Apex.OutputPanel();
    	
    	List<SobjectSortByNumberWrapper> sortedProductServiceMapping = new List<SobjectSortByNumberWrapper>();
		
		for (ProductServiceMapping__c psm : ProductServiceMapping__c.getAll().values())
		{
			sortedProductServiceMapping.add(new SobjectSortByNumberWrapper(psm, 'SectionOrder__c'));
		}
		
		sortedProductServiceMapping.sort();
		
		for (SobjectSortByNumberWrapper sList : sortedProductServiceMapping)
		{
			ProductServiceMapping__c psm = (ProductServiceMapping__c) sList.mainObj;

			Component.Apex.PageBlockSection pageBlockSec = new Component.Apex.PageBlockSection(title=psm.Section__c,collapsible=false,columns=2);
				
			Component.Apex.OutputField theNameField = new Component.Apex.OutputField();

			theNameField.expressions.value = '{!productService.' + s +'}';

			pageBlockSec.childComponents.add(theNameField);
			
			productSpecificInformation.childComponents.add(pageBlockSec);
	            
	    }
		
		return productSpecificInformation;
    }

and call the method from VF page some thing like this

<apex:outputpanel id="prodSpecInfo">
                <apex:dynamicComponent componentValue="{!productSpecificInformation}" />
            </apex:outputpanel>
This is just a sample that I used in my business scenario....






This was selected as the best answer