Friday, December 18, 2009

Creating a multilevel dependent picklist on Visualforce inside a Data table

Recently on working on a project I cam across a serious issue, creating a multilevel picklist with N-Level dependency.
e.g., Picklist one, select option, picklist two displays related values, select a value and the data for Picklist 3 are filtered based on picklist 1 and 2 and this goes on.
Lets increase the complexity a bit, you want to have this functionality in a data table with multiple rows.

The code for this seems tricky, but I did manage to write some.

The trick is create a wrapper class within you Apex:Class and bind it with the SelectList.

VF Page:

<apex:actionRegion >
<apex:pageBlockSection id="theSection" rendered="{!noLob}"> 
<apex:dataTable value="{!packages}" var="field" id="thetable" cellpadding="3px" id="dt">
<apex:column headerValue="Action">
<apex:CommandButton action="{!copyRow}" value="Copy" rerender="theSection" status="pleasewait">
<apex:param name="Assignment" Assignto="{!SelIndex}" value="{!field.index}"/>
</apex:CommandButton> 
</apex:column> 
<apex:column headerValue="Product Group">
<apex:selectList value="{!field.level1}" size="1" >
<apex:selectOptions value="{!field.level1Options}" /> 
<apex:actionSupport event="onchange" reRender="level2" status="pleasewait"> 
</apex:actionSupport>               
</apex:selectList>   
</apex:column>   
<apex:column headerValue="Products" >  
<apex:selectList id="level2" value="{!field.level2}" size="1" disabled="{!field.disable_level2}">
<apex:selectOptions value="{!field.level2Options}"/>     
</apex:selectList>  
</apex:dataTable>

And now the controller:

public class AddNewProductsController { 
public class myObject{
 public string level1 {get;set;} // The selected Level1 value in the Product Picklist on the modal panel
 public string level2 {get;set;}// The selected Level2 value in the Product Picklist on the modal panel
 public boolean disable_level2{get;set;}// The determines if Level2 value in the Product Picklist is disabled
 public boolean disable_level3{get;set;}// The determines if Level3 value in the Product Picklist is disabled
 public boolean FormRendered{get;set;}
 public myObject(){
 }
 public List getLevel1Options(){
 List options = new List();
 Options.add(new SelectOption('','--None--'));
 Options.add(new SelectOption('Product Group 1','Product Group 1')); 
Options.add(new SelectOption('Product Group 2','Product Group 2')); 
 Options.add(new SelectOption('Product Group 3','Product Group 3')); 
 Options.add(new SelectOption('Product Group 4','Product Group 4')); 
 return options;
 }
 
 public List getLevel2Options(){
 List options = new List();
 System.debug('==========='+level1+'%%%%%%%%%');
 options.add(new SelectOption('', '--None--')); 
 disable_level2=false;
 
 if(level1 == 'Product Group 1'){
 options.add(new SelectOption('Product1', 'Product1'));
 options.add(new SelectOption('Product2', 'Product2'));
 }else if(level1 == 'Product Group 2'){
 options.add(new SelectOption('Product1', 'Product1'));
 options.add(new SelectOption('Product15', 'Product15'));
 }else if(level1 == 'Product Group 3'){
 options.add(new SelectOption('Product2', 'Product2'));
 options.add(new SelectOption('Product23', 'Product23'));
 }else if(level1 == 'Product Group 4'){
 options.add(new SelectOption('Product16', 'Product16'));
 options.add(new SelectOption('Product12', 'Product12'));
 }else if(level1 == 'Product Group 5'){
 options.add(new SelectOption('Product16', 'Product16'));
 options.add(new SelectOption('Product1', 'Product1'));
 }else{
 disable_level2=true;
 }
 return options;
 }
}

This code will do your trick.

Hope it helps,
Cheers.
SiD