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
Prasan6Prasan6 

Multi select field in visualforce page

Hi All, 
We have a multi select html field where users can do CTRL + select multiple values, this should be stored in a multi select field. 

<div class="form-group">
                            <label class="control-label label-form" for="Attrib">Attrib<span class="mandatory"> *</span></label>
                            <div class="input-group">
                                <div class="input-group-addon">
                                    <span class="glyphicon glyphicon-pencil" aria-hidden="true"/>
                                </div>
                                <select multiple="multiple" class="form-control">
                                    <option>Colour</option>
                                    <option>Shape</option>
                                    <option>Size</option>
                                    <option>Weight</option>
                                </select>
                            </div>
                        </div>

How can I store the above selected values in a multi select field? 

Thanks, 
Prasanna
 
Best Answer chosen by Prasan6
Pankaj_GanwaniPankaj_Ganwani
Hi,

As you can see, we are calling javascript method namely pressButton() on click of the button. In that function, we are using a jquery iterator to fetch all the selected options from the picklist. I have given Id to picklist namely 'selectId' at line no.36 and then referencing its selected options and concatenating them in ';' separated format and atlast assigning this concatenated value to 'allSelected' variable. If you have multiple such select components on your page, give Id to each component and then do the below:
 
var picklist1 = '';
          $("#selectId1 option:selected").each(function(){
        picklist1+=picklist1!='' ? '; '+this.value : this.value;
      });

var picklist2 = ''; 
$("#selectId2 option:selected").each(function(){ 
picklist2+=picklist2!='' ? '; '+this.value : this.value; 
});

.......so on.

Here for understanding purpose, I have given picklist Id as selectId1, selectId2...so on and respective selected values are being hold in variables namely picklist1, picklist2...so on. Atlast of every iteration, call an action function and pass all these concatenated values to controller in one go.
function pressButton()
  {
      var picklist1 = '';
          $("#selectId1 option:selected").each(function(){
        picklist1+=picklist1!='' ? '; '+this.value : this.value;
      });

    var picklist2 = ''; 
    $("#selectId2 option:selected").each(function(){ 
    picklist2+=picklist2!='' ? '; '+this.value : this.value; 
    });

    .......so on.
    
    callFuncAF(picklist1, picklist2,...,so on);
    return false;
  }
Please let me know if this explanation enough for you to accomplish your task.
 

All Answers

Pankaj_GanwaniPankaj_Ganwani
Do you want to display the selected values in comma separated fashion in header or want to send the selected values to controller side?

If you just want to display the selected values in comma separated values then you can use Javascript:
 
function setPicklistValue(picklistName)
    {
        var listItems = $('#'+picklistName).next("div").find("div").find("ul").find("li");
        var commaseparatedString = '';
        var isAllSelected = false;
        var picklistSelectedOptions = $('#'+picklistName).val();
        if(picklistSelectedOptions!=null)
        {
            if(picklistSelectedOptions.indexOf('(all)')!=-1)
            {
            	for(var i = 0; i < listItems.length; i++)
            	{
            		var textValue = (listItems[i].childNodes[0].childNodes[0].textContent);
            		if(listItems[i].className == 'selected')
            		{
            			if(textValue!='(all)')
            				commaseparatedString = commaseparatedString == '' ? commaseparatedString.concat(textValue) : commaseparatedString.concat(', ',textValue);
            		}
            	}
            	
            	if(commaseparatedString!='')
            		listItems[0].className = '';
            }
            else
            {
            	for(var i = 0; i < listItems.length; i++)
            	{
            		var textValue = (listItems[i].childNodes[0].childNodes[0].textContent);
            		if(listItems[i].className == 'selected')
            		{
            			if(textValue!='(all)')
            				listItems[i].className = '';
            		}
            	}
            }
        }
        else
        {
            listItems[0].className = 'selected';
        }
        
        var pickVal = $('#'+picklistName).next("div").find("span")[0];
        if(commaseparatedString != '')
        {
            pickVal.innerHTML = commaseparatedString;
            $('#'+picklistName).next('div').find('button').attr('title',commaseparatedString);
        }
        else
        {
            pickVal.innerHTML = '(all)';
            $('#'+picklistName).next('div').find('button').attr('title','(all)');
            $('#'+picklistName).val($('#' + picklistName + ' option:first').val());
            listItems[0].setAttribute('class', 'selected');
        }
    }

 
Mehul MakwanaMehul Makwana
You can see my previous post regarding your question

https://developer.salesforce.com/forums/ForumsMain?id=906F0000000BaMqIAK
Prasan6Prasan6
Hi Pankaj, 

Thanks for your response. 
I want to send the selected values to the controller. 

Thanks, 
Prasanna
 
Pankaj_GanwaniPankaj_Ganwani
Okay, Since you are using Bootstrap, so there would be changes in the DOM structure if you see your picklist using inspect element. I did use below mentioned javascript code to pass the value from page to controller. You can also leverage the same:
 
function collectValues(picklistId)
{
      var listItems = $('#'+picklistId).next("div").find("div").find("ul").find("li");
      commaseparatedString  = '';
      for(var i = 0; i < listItems.length; i++)
            	{
            		var textValue = (listItems[i].childNodes[0].childNodes[0].textContent);
            		if(listItems[i].className == 'selected')
            		{
            			if(textValue!='')
            				commaseparatedString = commaseparatedString == '' ? commaseparatedString.concat(textValue) : commaseparatedString.concat('; ',textValue);
                        }
            	}

      callActionFunc(commaseparatedString);
return false;
      
}
Here callActionFunc is the name of the actionFunction which we using to call controller's method and passing semi colon separated value to controller.
Prasan6Prasan6
Thanks heaps Pankaj, 

couple of quesitons. From the bootsctap code above, how will I call the function: collectValues? 
Is callActionFunc a function in the controller? 

Thanks, 
Prasanna
Pankaj_GanwaniPankaj_Ganwani
Hi Prasanna,

To answer your questions, you will have to call this method on click of button to form a string separated by '; ' and atlast an action function will be called to pass this value to controller. Please refer below mentioned code to achieve this. This is working fine in my org:
 
<apex:page showHeader="false" docType="html-5.0" sidebar="false" cache="false" controller="TestBootstrap">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <link rel="stylesheet" href="{!$Resource.bootstrap}"/>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
  <script>  
  function pressButton()
  {
      var allSelected = '';
          $("#selectId option:selected").each(function(){
        allSelected+=allSelected!='' ? '; '+this.value : this.value;
      });
      alert(allSelected);
      callFuncAF(allSelected);
      return false;
  }
  </script>
</head>
<apex:form>

<apex:actionfunction name="callFuncAF" action="{!callFunc}" rerender="refresh">
   <apex:param name="selectedParam" assignTo="{!strSelectedValues}" value=""/>
</apex:actionfunction>

<div class="container">
<apex:outputPanel id="refresh">
<div class="form-group">
<label class="control-label label-form" for="Attrib">Attrib<span class="mandatory"> *</span></label>
<div class="input-group">
    <div class="input-group-addon">
        <span class="glyphicon glyphicon-pencil" aria-hidden="true"/>
    </div>
    <select multiple="multiple" class="form-control" id="selectId">
        <option>Colour</option>
        <option>Shape</option>
        <option>Size</option>
        <option>Weight</option>
    </select>
    <button id="pressId" onClick="return pressButton();">Submit</button>
</div>
</div>
</apex:outputPanel>
</div>
</apex:form>
</apex:page>
 
public class TestBootstrap
{
    public String strSelectedValues {get;set;}
    
    public void callFunc()
    {
       system.debug('====='+strSelectedValues);
    }
}

 
Prasan6Prasan6
Thanks once again Pankaj. 
Can you please explain how the selected values are passed in to the function? 
Actually I have several such fields in the page and I have a final submit button at the footer, thus I cannot have button for each of fields, So I need to capture the selected values to a string or something like that and then when I press submit button at the end, I will have to pass all the values for each of the concatenated string. (1 concatenated string for each field) 
Would be helpful if you can help me understand how values are passed in to the function pressButton()

Thanks again. 
 
Pankaj_GanwaniPankaj_Ganwani
Hi,

As you can see, we are calling javascript method namely pressButton() on click of the button. In that function, we are using a jquery iterator to fetch all the selected options from the picklist. I have given Id to picklist namely 'selectId' at line no.36 and then referencing its selected options and concatenating them in ';' separated format and atlast assigning this concatenated value to 'allSelected' variable. If you have multiple such select components on your page, give Id to each component and then do the below:
 
var picklist1 = '';
          $("#selectId1 option:selected").each(function(){
        picklist1+=picklist1!='' ? '; '+this.value : this.value;
      });

var picklist2 = ''; 
$("#selectId2 option:selected").each(function(){ 
picklist2+=picklist2!='' ? '; '+this.value : this.value; 
});

.......so on.

Here for understanding purpose, I have given picklist Id as selectId1, selectId2...so on and respective selected values are being hold in variables namely picklist1, picklist2...so on. Atlast of every iteration, call an action function and pass all these concatenated values to controller in one go.
function pressButton()
  {
      var picklist1 = '';
          $("#selectId1 option:selected").each(function(){
        picklist1+=picklist1!='' ? '; '+this.value : this.value;
      });

    var picklist2 = ''; 
    $("#selectId2 option:selected").each(function(){ 
    picklist2+=picklist2!='' ? '; '+this.value : this.value; 
    });

    .......so on.
    
    callFuncAF(picklist1, picklist2,...,so on);
    return false;
  }
Please let me know if this explanation enough for you to accomplish your task.
 
This was selected as the best answer
Prasan6Prasan6
Thanks heaps Pankaj, you helped me to undertand the logic.