This particular topic is entirely related to how to define MultiSelect Dependent Picklist in visualforce Page.
Problem
Some times customer/client may require to have a functionality where end user can choose multiple field values from multi select picklist and based on that master picklist user should be able to select a multiple child values from the another multi select picklist.Solution:
VF Page:
<apex:page standardController="Lead" extensions="MultiSelectController" >
<script>
function clickAdd(){
Refresh();
}
function clickRemove(){
Remove();
}
function clickChildAdd(){
AddChild();
}
function clickChildRemove(){
RemoveChild();
}
</script>
<style>
.sidebarCollapsed #sidebarDiv {
display: none;
}
.rightAligned{
text-align: right;
}
.leftAligned{
text-align:left;
}
.centerAligned{
text-align : center;
}
.centerAligned p{
white-space: normal;
margin:0;
padding:0;
min-width:100px;
}
.headerRow{
vertical-align:middle;
}
.label{
width:100%;
font-weight:bold;
float:left;
}
.multilist{
float:left;
vertical-align:middle
}
.multilist p {
padding: 0;
text-align: center;
white-space: normal;
width: 50px;
margin:0;
}
.multilist .btn{
margin-top:3px;
margin-left:10px;
margin-right:10px;
}
.detailList .empty{
display:none;
}
</style>
<apex:form id="form1">
<apex:outputPanel id="panel1">
<div style="background-color:#BFD2FF;border-radius:20px;">
<center>
<br/>
<apex:actionFunction action="{!actionUpdatePicklistVals}" name="Refresh" rerender="panel1"/>
<apex:actionFunction action="{!actionRemovePicklistVals}" name="Remove" rerender="panel1"/>
<apex:actionFunction action="{!addChildPicklistVals}" name="AddChild" rerender="panel1"/>
<apex:actionFunction action="{!RemoveChildPicklistVals}" name="RemoveChild" rerender="panel1"/>
<Table>
<TR><TD colspan="2"><b>Product Interest:</b></TD></TR>
<TR><TD><b> Available</b></TD><TD></TD><TD><b> Chosen</b></TD></TR>
<TR><TD>
<apex:selectList value="{!parentPicklistVal}" multiselect="true" size="5" style="width:250px;hight:500px">
<apex:selectOptions value="{!parentPicklistOptions}" />
</apex:selectList>
</TD><TD><br></br><a href="#" title="Add"><img src="/s.gif" alt="Add" class="picklistArrowRight" onclick="clickAdd()" style="cursor:pointer;" title="Add"/></a>
<br></br><br></br><a href="#" title="Remove"><img src="/s.gif" alt="Remove" class="picklistArrowLeft" onclick="clickRemove()" style="cursor:pointer;" title="Remove"/></a>
</TD><TD>
<apex:selectList value="{!selectedparentPicklistVal}" multiselect="true" size="5" style="width:250px;hight:500px">
<apex:selectOptions value="{!SelectedParentPicklistOptions}" />
</apex:selectList>
</TD></TR>
</Table>
<Table>
<TR><TD colspan="2"><b>Product Business Unit:</b></TD></TR>
<TR><TD><b> Available</b></TD><TD></TD><TD><b> Chosen</b></TD></TR>
<TR><TD>
<apex:selectList value="{!childPicklistVal}" multiselect="true" size="5" style="width:250px">
<apex:selectOptions value="{!ChildPicklistOptions}" />
</apex:selectList>
</TD><TD><br></br><a href="#" title="Add"><img src="/s.gif" alt="Add" class="picklistArrowRight" onclick="clickChildAdd()" style="cursor:pointer;" title="Add"/></a>
<br></br><br></br><a href="#" title="Remove"><img src="/s.gif" alt="Remove" class="picklistArrowLeft" onclick="clickChildRemove()" style="cursor:pointer;" title="Remove"/></a>
</TD><TD>
<apex:selectList value="{!selectedchildPicklistVal}" multiselect="true" size="5" style="width:250px">
<apex:selectOptions value="{!SelectedChildPicklistOptions}" />
</apex:selectList>
</TD></TR>
</Table>
<br/>
</center>
</div>
</apex:outputPanel>
</apex:form>
</apex:page>
Apex Class:
public class MultiSelectController {
public MultiSelectController(ApexPages.StandardController controller) {
MultiSelectDefaultLoad();
}
public String[] parentPicklistVal {public get; public set;}
public String[] selectedparentPicklistVal {public get; public set;}
public String[] childPicklistVal {public get; public set;}
public String[] selectedchildPicklistVal {public get; public set;}
public List<SelectOption> ParentPicklistOptions{get;set;}
public List<SelectOption> SelectedParentPicklistOptions{get;set;}
public List<SelectOption> ChildPicklistOptions{get;set;}
public list<SelectOption> SelectedChildPicklistOptions{get;set;}
public lead lead{get;set;}
public list<string> lstgroup=new list<string>();
public list<string> lstSubgroup=new list<string>();
private Map<String, List<String>> parentChildMap;
public boolean bIsRemoved{get;set;}
public boolean bIsRemovedChild{get;set;}
public boolean bIsAddChild{get;set;}
private String[] parentOpts = new String[] { 'Drilling', 'Evaluation','Completion','Production','Intervention' };
private String[] childMultiOpts = new String[] { 'Aluminum-alloy tubulars', ' Cementing Services', 'Closed-loop drilling',' Downhole drilling products','Drilling fluids & waste management','Drilling Services','Elastomer products','Well construction','Wellhead systems' };
public void MultiSelectDefaultLoad(){
bIsRemoved=false;
bIsRemovedChild=false;
bIsAddChild=false;
list<string> lstOne=new list<string>();
lstOne.add('Aluminum-alloy tubulars');
lstOne.add('Cementing Services');
lstOne.add('Closed-loop drilling');
lstOne.add('Downhole drilling products');
lstOne.add('Drilling fluids & waste management');
lstOne.add('Drilling services');
lstOne.add('Elastomer products');
lstOne.add('Well construction');
lstOne.add('Wellhead systems');
list<string> lst2=new list<string>();
lst2.add('Geomechanics services');
lst2.add('Logging-while-drilling(LWD)');
lst2.add('Surface logging systems');
lst2.add('Laboratory services');
lst2.add('Testing & production services');
lst2.add('Wireline services');
list<string> lst3=new list<string>();
lst3.add('Completion chemicals');
lst3.add('Flow assurance chemicals');
lst3.add('Cased-hole completions');
lst3.add('Openhole completions');
lst3.add('Reservoir simulation');
lst3.add('Sand Control');
list<string> lst4=new list<string>();
lst4.add('Artificial-lift systems');
lst4.add('Chemical services');
lst4.add('Pipeline & specially services');
lst4.add('Pressure pumping services');
lst4.add('Colled-tubing technologies');
lst4.add('Johnson screens');
lst4.add('Pump & fluid systems');
lst4.add('Surface production quipment');
lst4.add('Production & produced-water systems');
lst4.add('Production optimization');
list<string> lst5=new list<string>();
lst5.add('Fishing services');
lst5.add('Thru-tubing services');
lst5.add('Wellbore cleaning services');
lst5.add('Intervention chemicals');
lst5.add('Multilateral services');
lst5.add('Re-entry services');
lst5.add('Well abandonment services');
lst5.add('Well servicing');
parentChildMap=new Map<String, List<String>>();
parentChildMap.put(parentOpts[0], lstOne);
parentChildMap.put(parentOpts[1], lst2);
parentChildMap.put(parentOpts[2], lst3);
parentChildMap.put(parentOpts[3], lst4);
parentChildMap.put(parentOpts[4], lst5);
//parentChildMap.put(parentOpts[1], (new String[]{childMultiOpts[2], childMultiOpts[3]}));
//parentChildMap.put(parentOpts[2], (new String[]{childMultiOpts[4], childMultiOpts[5], childMultiOpts[6]}));
ParentPicklistOptions=new List<SelectOption>();
SelectedParentPicklistOptions=new List<SelectOption>();
ChildPicklistOptions=new List<SelectOption>();
SelectedChildPicklistOptions=new List<SelectOption>();
List<SelectOption> selectOpts = new List<SelectOption>();
for(String s : parentOpts ){
selectOpts.add(new SelectOption(s, s));
}
ParentPicklistOptions.addAll(selectOpts);
}
public PageReference actionUpdatePicklistVals() {
// this doesn't really need to do anything, since the picklists should be updated when their getters call after returning
bIsRemoved=false;
List<SelectOption> selectOpts = new List<SelectOption>();
if (parentPicklistVal != null && parentPicklistVal.size() > 0 ) {
for(String s : parentPicklistVal ){
selectOpts.add(new SelectOption(s, s));
}
}
SelectedParentPicklistOptions.addAll(selectOpts);
List<System.SelectOption> AllPRaentSelectedVal=SelectedParentPicklistOptions;
set<string> setselectVal=new set<string>();
for(System.SelectOption opt:AllPRaentSelectedVal){
setselectVal.add(opt.getvalue());
}
ParentPicklistOptions.clear();
List<SelectOption> selectOpts2 = new List<SelectOption>();
for(String s : parentOpts ){
if(!setselectVal.contains(s))
selectOpts2.add(new SelectOption(s, s));
}
ParentPicklistOptions.addAll(selectOpts2);
fCallAddToChildAvailableList();
return null;
}
public void fCallAddToChildAvailableList(){
List<System.SelectOption> AllPRaentSelectedVal=SelectedParentPicklistOptions;
set<string> setselectVal=new set<string>();
for(System.SelectOption opt:AllPRaentSelectedVal){
setselectVal.add(opt.getvalue());
}
List<SelectOption> selectOpts = new List<SelectOption>();
Set<String> possibleOpts = new Set<String>();
for ( String val : setselectVal){
if(parentChildMap.get(val)!=null)
possibleOpts.addAll(parentChildMap.get(val));
}
list<system.Selectoption> AllselectedChildPickListOption=SelectedChildPicklistOptions;
set<string> setselectedChildOpt=new set<string>();
for(System.SelectOption opt:AllselectedChildPickListOption){
setselectedChildOpt.add(opt.getvalue());
}
for ( String s : possibleOpts ){
if(!setselectedChildOpt.contains(s))
selectOpts.add(new SelectOption(s, s));
}
ChildPicklistOptions.clear();
ChildPicklistOptions.addAll(selectOpts);
}
public PageReference addChildPicklistVals(){
bIsRemovedChild=false;
bIsAddChild=true;
List<SelectOption> selectOpts = new List<SelectOption>();
if (childPicklistVal != null && childPicklistVal .size() > 0 ) {
for(String s : childPicklistVal ){
selectOpts.add(new SelectOption(s, s));
}
}
SelectedChildPicklistOptions.addAll(selectOpts);
ChildPicklistOptions.clear();
List<System.SelectOption> AllPRaentSelectedVal=SelectedParentPicklistOptions;
set<string> setselectVal=new set<string>();
for(System.SelectOption opt:AllPRaentSelectedVal){
setselectVal.add(opt.getvalue());
}
List<SelectOption> selectOpts2 = new List<SelectOption>();
Set<String> possibleOpts = new Set<String>();
for ( String val : setselectVal){
if(parentChildMap.get(val)!=null)
possibleOpts.addAll(parentChildMap.get(val));
}
list<system.Selectoption> AllselectedChildPickListOption=SelectedChildPicklistOptions;
set<string> setselectedChildOpt=new set<string>();
for(System.SelectOption opt:AllselectedChildPickListOption){
setselectedChildOpt.add(opt.getvalue());
}
for (String s : possibleOpts ){
if(!setselectedChildOpt.contains(s))
selectOpts2.add(new SelectOption(s, s));
}
ChildPicklistOptions.addAll(selectOpts2);
return null;
}
public PageReference actionRemovePicklistVals() {
// this doesn't really need to do anything, since the picklists should be updated when their getters call after returning
bIsRemoved=true;
set<string> setRemoveSelected=new set<string>();
if (selectedparentPicklistVal != null && selectedparentPicklistVal .size() > 0 ) {
for(String s : selectedparentPicklistVal){
setRemoveSelected.add(s);
}
}
List<System.SelectOption> AllPRaentSelectedVal=SelectedParentPicklistOptions;
set<string> setselectVal=new set<string>();
for(System.SelectOption opt:AllPRaentSelectedVal){
setselectVal.add(opt.getvalue());
}
setselectVal.removeAll(setRemoveSelected);
SelectedParentPicklistOptions.clear();
List<SelectOption> selectOpts2 = new List<SelectOption>();
for(string s:setselectVal){
selectOpts2.add(new SelectOption(s, s));
}
SelectedParentPicklistOptions.addAll(selectOpts2);
RefreshParentOption();
RefreshChildOption();
return null;
}
public void RefreshParentOption(){
ParentPicklistOptions.clear();
List<System.SelectOption> AllPRaentSelectedVal=SelectedParentPicklistOptions;
set<string> setselectVal=new set<string>();
for(System.SelectOption opt:AllPRaentSelectedVal){
setselectVal.add(opt.getvalue());
}
List<SelectOption> selectOpts2 = new List<SelectOption>();
for(String s : parentOpts ){
if(!setselectVal.contains(s))
selectOpts2.add(new SelectOption(s, s));
}
ParentPicklistOptions.addAll(selectOpts2);
}
public void RefreshChildOption(){
ChildPicklistOptions.clear();
List<System.SelectOption> AllPRaentSelectedVal=SelectedParentPicklistOptions;
set<string> setselectVal=new set<string>();
for(System.SelectOption opt:AllPRaentSelectedVal){
setselectVal.add(opt.getvalue());
}
List<SelectOption> selectOpts2 = new List<SelectOption>();
Set<String> possibleOpts = new Set<String>();
for ( String val : setselectVal){
if(parentChildMap.get(val)!=null)
possibleOpts.addAll(parentChildMap.get(val));
}
list<system.SelectOption> lstSelectedChildPickListOpt=SelectedChildPicklistOptions;
set<string> setAlreadySelectedChildPickListVal=new set<string>();
for(system.SelectOption opt:lstSelectedChildPickListOpt){
setAlreadySelectedChildPickListVal.add(opt.getValue());
}
list<system.selectoption> lstSelectOpt=new list<system.selectoption>();
for (String s : possibleOpts ){
if(!setAlreadySelectedChildPickListVal.contains(s))
lstSelectOpt.add(new SelectOption(s, s));
}
ChildPicklistOptions.addAll(lstSelectOpt);
}
public PageReference RemoveChildPicklistVals(){
//bIsRemovedChild=true;
//bIsAddChild=false;
set<string> setSelectedChildItem=new set<string>();
if(selectedchildPicklistVal!=null && selectedchildPicklistVal.size()>0){
for(string s:selectedchildPicklistVal){
setSelectedChildItem.add(s);
}
}
list<system.SelectOption> lstSelectedChildOption=new list<system.SelectOption>();
lstSelectedChildOption=SelectedChildPicklistOptions;
set<string> setAllOptionSelectedChild=new set<string>();
for(system.SelectOption opt:lstSelectedChildOption){
setAllOptionSelectedChild.add(opt.getValue());
}
setAllOptionSelectedChild.removeAll(setSelectedChildItem);
list<system.selectoption> lstSelectOpt=new list<system.selectoption>();
for(string s:setAllOptionSelectedChild){
lstSelectOpt.add(new SelectOption(s, s));
}
SelectedChildPicklistOptions.clear();
SelectedChildPicklistOptions.addAll(lstSelectOpt);
RefreshChildOption();
return null;
}
}
6 Comments
Hi Amul,
ReplyDeletethis is a great solution and I was able to adapt that to our dependant multi-picklists and it works well on its own, however, when I try to integrate the code into my existing visualforce page, the values cannot be selected any more. Do you know how this can be fixed? Thanks, Kathleen
Hi Kathleen,
DeleteFollowing code line is for mapping purpose. (Means ti define parent and its child elements).
Just verify these line's once again.and let me know if you see problem again. And one more thing just put a debug statement and see in the debug log to fix this.
parentChildMap=new Map>();
parentChildMap.put(parentOpts[0], lstOne);
parentChildMap.put(parentOpts[1], lst2);
parentChildMap.put(parentOpts[2], lst3);
parentChildMap.put(parentOpts[3], lst4);
parentChildMap.put(parentOpts[4], lst5);
Hi Kathleen,
DeleteFollowing code line is for mapping purpose. (Means ti define parent and its child elements).
Just verify these line's once again.and let me know if you see problem again. And one more thing just put a debug statement and see in the debug log to fix this.
parentChildMap=new Map>();
parentChildMap.put(parentOpts[0], lstOne);
parentChildMap.put(parentOpts[1], lst2);
parentChildMap.put(parentOpts[2], lst3);
parentChildMap.put(parentOpts[3], lst4);
parentChildMap.put(parentOpts[4], lst5);
Hi Amul,
ReplyDeleteThis is a great solution.. can you provide me with a similar example that has the controlling picklist as a normal picklist and the dependent picklist as a multiselect picklist.Your help would be greatly appreciated.
Thanks,
Krishna Dev
Hi Amul,
ReplyDeleteThis is a great solution would you please provide an advise on How would I make the save() for these values
I quite like reading an article that can make people think. Also, thanks for allowing for me to comment! multiselect definicja
ReplyDelete