+ Start a Discussion
ForceRookieForceRookie 

How to multiselect the lightning:combobox?

I have a working dynamic picklist, but I want it to select multiple options. Help me to do it, please..
    
Here's me code:

Lightning Component

<aura:attribute name="options" type="String[]" description="options" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:attribute name="newOpp" type="Opportunity" default="{'sobjectype': 'Opportunity',
                                                           'Name': '',
                                                           'CloseDate': '',
                                                           'Amount': '',
                                                           'StageName': '',
                                                           'Donate_to__c': ''}"/>
															  
<lightning:combobox aura:id="MultiSelect"
							label="Donate to"
							placeholder="Select 1 or more options"
							value="{!v.newOpp.Donate_to__c}"
							required="true"
							messageWhenValueMissing="Hey! Don't forget me!"/>

JavaScript Controller

doInit : function(component, event, helper) {
        var action = component.get("c.getDonateTo");
        var input = component.find("MultiSelect");
        var opts=[];
        
        action.setCallback(this, function(a) {
            for(var i=0;i< a.getReturnValue().length;i++){
                opts.push({"class": "optionClass", label: a.getReturnValue()[i], value: a.getReturnValue()[i]});
            }
            input.set("v.options", opts);
            
        });
        $A.enqueueAction(action);
		
},
Controller class
@AuraEnabled        
public static List<String> getDonateTo(){
  List<String> options = new List<String>();
  Schema.DescribeFieldResult fieldResult = Opportunity.Donate_to__c.getDescribe();
  List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
      for (Schema.PicklistEntry f: ple) {
            options.add(f.getLabel());
      }
      return options;
}
Raj VakatiRaj Vakati
lightning:combobox is an input element that enables single selection from a list of options. The result of the selection is displayed as the value of the input

You cannt able to do it with lightning:combobox 



Use  lightning:dualListbox  component represents two side-by-side list boxes. Select one or more options in the list on the left. Move selected options to the list on the right. The order of the selected options is maintained and you can reorder options.


refer this link 

https://developer.salesforce.com/docs/component-library/bundle/lightning:dualListbox/documentation
ForceRookieForceRookie
Raj Vakati,
    No, it's posible if we will customize it, just like the example on this link:
    https://www.soliantconsulting.com/blog/create-a-custom-salesforce-lightning-multiselect-component
    
    But I dunno how to apply it to my code since we're using different code.
David Roberts 4David Roberts 4
The Combobox only allows selection of one option - although it does have the very nice tick icon.
Below is a solution based on lightning:select where I've used '-->' to represent a selected option and built it into the label string.
I've used the index of the selection and a parallel array of wrapper objects that include a 'selected' flag.
All the events are handled by the lightning:select component rather than some of the more complex solutions available using SLDS and events.
You will find this very easy to customise, especially the 'label' of the options.

Apex controller:
public class ExampleMultiSelectController {
    
    @AuraEnabled
    public static List<accountWrapper> aeGetSomeAccounts(){
        
        List<accountWrapper> lstReturn = new List<accountWrapper>();
        List<Account> lstAccounts = [SELECT Id, Name, Phone, BillingCity FROM Account ORDER BY Name LIMIT 10];
        
        if (lstAccounts.size()>0){
            for (Account anAccount : lstAccounts) {
                accountWrapper aWrapper = new accountWrapper();
                aWrapper.wSelected = false;
                aWrapper.wAccount = anAccount;             
                lstReturn.add(aWrapper);
             }//next anAccount
        }//endif lstAccounts has entries
        return lstReturn;
    }//getSomeAccounts
    
    public class accountWrapper{
        @AuraEnabled public Boolean wSelected {get; set;}
        @AuraEnabled public Account wAccount{get;set;} 
    }//accountWrapper
    
    
}//ExampleMultiSelectController

Aura Component:
<aura:component controller="ExampleMultiSelectController" implements="force:appHostable,flexipage:availableForAllPageTypes" >
<!-- example by Dave Roberts, Logicom Computer Services (UK) Ltd -->    
    <aura:attribute name="accounts" type="Object"/>
    <aura:attribute name="accountOptions" type="List" default="[]"/>
    <aura:attribute name="selectLabel" type="String" default="Select..."/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    <lightning:select  aura:id="idSelectOptions"  label="{!v.selectLabel}" required="false" onchange="{! c.onOptionSelected }">
        <aura:iteration items="{!v.accountOptions}" var="element"  indexVar="idx">
            <option text="{!element.label}"  value = "{!idx}" ></option>
        </aura:iteration>
    </lightning:select>
</aura:component>
Aura Controller:
({
    //ExampleMultiSelect aura bundle
    //created as example for https://developer.salesforce.com/forums/?id=9060G0000005qzWQAQ
    doInit: function (component, event, helper) {
        
        var action = component.get('c.aeGetSomeAccounts');
        
        action.setCallback(this, $A.getCallback(function (response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var retVal = response.getReturnValue();
                component.set("v.accounts",retVal);
                //push into accountOptions
                var items = [];
                var item;
                item = {
                    "label": "Select options...",
                    "value": null
                };
                items.push(item);
                for (var i = 0; i < retVal.length; i++) {
                    
                    //console.log(retVal[i]);
                    item = {
                        "label": retVal[i].wAccount.Name + ' - '+retVal[i].wAccount.BillingCity + ' - '+retVal[i].wAccount.Phone,
                        "value": retVal[i].wAccount.Id
                    };
                    items.push(item);
                }
                component.set("v.accountOptions", items);
            } else if (state === "ERROR") {
                alert('Error');
            }//endif success
        }));
        
        $A.enqueueAction(action);
    },//doInit
    
    onOptionSelected: function (cmp, event, helper) {
        var index = cmp.find("idSelectOptions").get("v.value");
        //so now we can update the array and select this item
        //note: options has an additional element so adjust the index
        var arrayAccounts = [];
        arrayAccounts = cmp.get("v.accounts");
        var changedItem = arrayAccounts [index-1];
        //toggle the selection
        changedItem.wSelected = !changedItem.wSelected;
        arrayAccounts[index-1] = changedItem;
        cmp.set("v.accounts",arrayAccounts);
        
        
        //update the options
        var arrayOfOptions = [];
        arrayOfOptions = cmp.get("v.accountOptions");
        var changedOption = arrayOfOptions[index];
        if (changedItem.wSelected){
            changedOption.label =  '--> ' + changedItem.wAccount.Name +' - '+ changedItem.wAccount.BillingCity +' - '+changedItem.wAccount.Phone;
            console.log('selected -- '+changedOption.label);
            
        }else{
            changedOption.label =  changedItem.wAccount.Name+' - '+ changedItem.wAccount.BillingCity +' - ' + changedItem.wAccount.Phone;
        }//endif selected
        
        arrayOfOptions[index] = changedOption;
        //count number that are selected
        let numSelected = 0
        arrayAccounts.forEach(function(element) {
            //console.log(element);
            if (element.wSelected){numSelected++;}
            
        });
        arrayOfOptions[0].label = numSelected+" Selected";
        cmp.set("v.accountOptions", arrayOfOptions);
        cmp.set("v.selectLabel",numSelected+" Selected");
        cmp.find("idSelectOptions").set("v.value",0);
        
    },//onOptionSelected
})

Multi-select in operation

Whilst the original question was posted nearly three years ago, I'm sure others will find this useful.
I trust @forcerookie is, by now, now forceexpert!