custom dependent picklist

Custom Dependent Picklist Field With lightning:select In Lightning Component

Lightning Component

Hey guys, today in this post we are going to create a new updated version of Custom Dependent Picklist fields using ‘lightning:select‘ base component in salesforce.

custom-dependent-picklist lightning

Prerequisites : basic understanding of Lightning Component & apex Programming
Step  0 : Setup Picklist field dependency

In this post , first we have create 2 custom picklist fields on salesforce  standard Contact object

Country__c &  City__c

then set field dependency. here country is the controller field  and city is the dependent field.

Custom dependent picklist salesforce sfdcmonkey

Step  1 : Create apex controller
[dependentPicklist_UpdateCtrl.apxc]
public class dependentPicklist_UpdateCtrl {
    @AuraEnabled 
    public static Map<String, List<String>> getDependentMap(sObject objDetail, string contrfieldApiName,string depfieldApiName) {
        String controllingField = contrfieldApiName.toLowerCase();
        String dependentField = depfieldApiName.toLowerCase();
        
        Map<String,List<String>> objResults = new Map<String,List<String>>();
        
        Schema.sObjectType objType = objDetail.getSObjectType();
        if (objType==null){
            return objResults;
        }
        
        Map<String, Schema.SObjectField> objFieldMap = objType.getDescribe().fields.getMap();
        
        if (!objFieldMap.containsKey(controllingField) || !objFieldMap.containsKey(dependentField)){
            return objResults;     
        }
        
        Schema.SObjectField theField = objFieldMap.get(dependentField);
        Schema.SObjectField ctrlField = objFieldMap.get(controllingField);
        
        List<Schema.PicklistEntry> contrEntries = ctrlField.getDescribe().getPicklistValues();
        List<PicklistEntryWrapper> depEntries = wrapPicklistEntries(theField.getDescribe().getPicklistValues());
        List<String> controllingValues = new List<String>();
        
        for (Schema.PicklistEntry ple : contrEntries) {
            String label = ple.getLabel();
            objResults.put(label, new List<String>());
            controllingValues.add(label);
        }
        
        for (PicklistEntryWrapper plew : depEntries) {
            String label = plew.label;
            String validForBits = base64ToBits(plew.validFor);
            for (Integer i = 0; i < validForBits.length(); i++) {
                String bit = validForBits.mid(i, 1);
                if (bit == '1') {
                    objResults.get(controllingValues.get(i)).add(label);
                }
            }
        }
        return objResults;
    }
    
    public static String decimalToBinary(Integer val) {
        String bits = '';
        while (val > 0) {
            Integer remainder = Math.mod(val, 2);
            val = Integer.valueOf(Math.floor(val / 2));
            bits = String.valueOf(remainder) + bits;
        }
        return bits;
    }
    
    public static String base64ToBits(String validFor) {
        if (String.isEmpty(validFor)) return '';
        
        String validForBits = '';
        
        for (Integer i = 0; i < validFor.length(); i++) {
            String thisChar = validFor.mid(i, 1);
            Integer val = base64Chars.indexOf(thisChar);
            String bits = decimalToBinary(val).leftPad(6, '0');
            validForBits += bits;
        }
        
        return validForBits;
    }
    
    private static final String base64Chars = '' +
        'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
        'abcdefghijklmnopqrstuvwxyz' +
        '0123456789+/';
    
    
    private static List<PicklistEntryWrapper> wrapPicklistEntries(List<Schema.PicklistEntry> PLEs) {
        return (List<PicklistEntryWrapper>)
            JSON.deserialize(JSON.serialize(PLEs), List<PicklistEntryWrapper>.class);
    }
    
    public class PicklistEntryWrapper{
        public String active {get;set;}
        public String defaultValue {get;set;}
        public String label {get;set;}
        public String value {get;set;}
        public String validFor {get;set;}
        public PicklistEntryWrapper(){            
        }
        
    }
}
  • you don’t need to change anything in above apex classes.
Step  2 : Create Lightning Component
DependentPicklist.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction"
                access="global"
                controller="dependentPicklist_UpdateCtrl">
    <!-- call doInit function on component load -->  
    <aura:handler name="init" value="this" action="{!c.doInit}"/>
    
    <!-- aura attributes-->  
    <aura:attribute name="listControllingValues" type="list" default="[]" description="to store controller field values"/>
    <aura:attribute name="listDependingValues" type="list" default="['--- None ---']" description="to store dependent field values"/>
    <aura:attribute name="depnedentFieldMap" type="map" description="map to store dependent values with controlling value"/>
    <aura:attribute name="bDisabledDependentFld" type="boolean" default="true"/> 
    
    <aura:attribute name="objDetail" type="contact" default="{'sobjectType' : 'contact'}"/>
    <aura:attribute name="controllingFieldAPI" type="string" default="Country__c" description="store field API name of Controller field"/>
    <aura:attribute name="dependingFieldAPI" type="string" default="City__c" description="store field API name of dependent field"/>
    
    <!--Controller Field-->
    <lightning:layoutItem size="12" padding="around-small">    
        <lightning:select name="controllerFld"
                          value="{!v.objDetail.Country__c}"
                          label="Country"
                          onchange="{!c.onControllerFieldChange}">
            <aura:iteration items="{!v.listControllingValues}" var="val">
                <option value="{!val}">{!val}</option>
            </aura:iteration>
        </lightning:select>
    </lightning:layoutItem>
    
    <!--Dependent Field-->
    <lightning:layoutItem size="12" padding="around-small">
        <lightning:select name="dependentFld"
                          value="{!v.objDetail.City__c}"
                          label="City"
                          disabled="{!v.bDisabledDependentFld}">
            <aura:iteration items="{!v.listDependingValues}" var="val">
                <option value="{!val}">{!val}</option>
            </aura:iteration>
        </lightning:select>
    </lightning:layoutItem>
    
</aura:component>
DependentPicklistController.js
({
    doInit : function(component, event, helper) { 
        // get the fields API name and pass it to helper function  
        var controllingFieldAPI = component.get("v.controllingFieldAPI");
        var dependingFieldAPI = component.get("v.dependingFieldAPI");
        var objDetails = component.get("v.objDetail");
        // call the helper function
        helper.fetchPicklistValues(component,objDetails,controllingFieldAPI, dependingFieldAPI);
    },
    
    onControllerFieldChange: function(component, event, helper) {     
        var controllerValueKey = event.getSource().get("v.value"); // get selected controller field value
        var depnedentFieldMap = component.get("v.depnedentFieldMap");
        
        if (controllerValueKey != '--- None ---') {
            var ListOfDependentFields = depnedentFieldMap[controllerValueKey];
            
            if(ListOfDependentFields.length > 0){
                component.set("v.bDisabledDependentFld" , false);  
                helper.fetchDepValues(component, ListOfDependentFields);    
            }else{
                component.set("v.bDisabledDependentFld" , true); 
                component.set("v.listDependingValues", ['--- None ---']);
            }  
            
        } else {
            component.set("v.listDependingValues", ['--- None ---']);
            component.set("v.bDisabledDependentFld" , true);
        }
    },
})
Check also :  Custom Multi-Select Picklist In Lightning Component With Select2 jQuery Plugin
DependentPicklistHelper.js
({
    fetchPicklistValues: function(component,objDetails,controllerField, dependentField) {
        // call the server side function  
        var action = component.get("c.getDependentMap");
        // pass paramerters [object definition , contrller field name ,dependent field name] -
        // to server side function 
        action.setParams({
            'objDetail' : objDetails,
            'contrfieldApiName': controllerField,
            'depfieldApiName': dependentField 
        });
        //set callback   
        action.setCallback(this, function(response) {
            if (response.getState() == "SUCCESS") {
                //store the return response from server (map<string,List<string>>)  
                var StoreResponse = response.getReturnValue();
                
                // once set #StoreResponse to depnedentFieldMap attribute 
                component.set("v.depnedentFieldMap",StoreResponse);
                
                // create a empty array for store map keys(@@--->which is controller picklist values) 
                var listOfkeys = []; // for store all map keys (controller picklist values)
                var ControllerField = []; // for store controller picklist value to set on lightning:select. 
                
                // play a for loop on Return map 
                // and fill the all map key on listOfkeys variable.
                for (var singlekey in StoreResponse) {
                    listOfkeys.push(singlekey);
                }
                
                //set the controller field value for lightning:select
                if (listOfkeys != undefined && listOfkeys.length > 0) {
                    ControllerField.push('--- None ---');
                }
                
                for (var i = 0; i < listOfkeys.length; i++) {
                    ControllerField.push(listOfkeys[i]);
                }  
                // set the ControllerField variable values to country(controller picklist field)
                component.set("v.listControllingValues", ControllerField);
            }else{
                alert('Something went wrong..');
            }
        });
        $A.enqueueAction(action);
    },
    
    fetchDepValues: function(component, ListOfDependentFields) {
        // create a empty array var for store dependent picklist values for controller field  
        var dependentFields = [];
        dependentFields.push('--- None ---');
        for (var i = 0; i < ListOfDependentFields.length; i++) {
            dependentFields.push(ListOfDependentFields[i]);
        }
        // set the dependentFields variable values to store(dependent picklist field) on lightning:select
        component.set("v.listDependingValues", dependentFields);
        
    },
    
})

 

  • check above code comments.
  • You just need to change the object API Name/Type on line number 15.[DependentPicklist.cmp].
  • And change dependent field and controller field API Names on line number 16 – 17.[DependentPicklist.cmp].

TestApp.app

<aura:application extends="force:slds">
    <c:DependentPicklist/>
<!-- here c: is org. default namespace prefix-->
</aura:application>
 

want to create 3 level picklist field dependency ? check example here 

Like our facebook page for new post updates.? & Don’t forget to bookmark this site for your future reference.

 Let us know if it helps you 🙂

people also check : How to use SVG in Salesforce Lightning Component ?

 

15 comments

  • Hi,

    Thanks a lot for this component. Its really helpful!

    I need to store the values of the above component details along with another component values by clicking on save button. May I know how this can be achieved please!

    Thanks in advance:)

  • Hi Piyush,

    This is great, thanks! How would you adapt this code to include two dependent picklist fields being controlled by the same controlling picklist field on the same form?

  • i copied the code and all done but i am not getting the values in both controlled and dependant field,

    here i changed the field api names as country__  c  and city__c,

    still i am not getting the values.

    can you please help me in this

  • How can I pass the value and the label of the picklist,
    because right now the label is only being obtained, but when I translate 
    at the moment the insertion in salesforce throws me the error, that the value 
    does not exist in the selection list, please help!
    
    				
  • I want to create dependent picklist having three dependent columns and it should applies independently on multiple rows. It means picklist fields in Columns are dependent but picklist fields in rows are not dependent to each other .I use the code given in http://sfdcmonkey.com/2018/08/31/dependent-picklist-lightningselect-lightning-salesforce/ , but it makes rows also dependent on each other. Please help if any one has code for this.

    This is my component code:

    <aura:iteration items=”{!v.NewoperationalApproverData}” var=”OperationalAPProver” indexVar=”rowIndex”>
    <tr class=”slds-text-title_caps”>
    <td>

    {!rowIndex + 1}

                            <lightning:select name="Division"
                                    value="{!OperationalAPProver.selectedProdDiv}"
                                    tabindex="{!rowIndex}"
                                    onchange="{!c.onControllerFieldChange}" label="{!rowIndex}">
                            <aura:iteration items="{!v.listControllingValues}" var="val">
                                <option value="{!val}">{!val}</option>
                            </aura:iteration>
                            </lightning:select>
                        </td>                    
                        <td>
    
                            <lightning:select name="LO"
                                    value="{!OperationalAPProver.selectedLo}"
                                    tabindex="{!rowIndex}"
    
                                    onchange="{!c.onSubControllerFieldChange}">
                            <aura:iteration items="{!v.listDependingValues}" var="val">
                                <option value="{!val}">{!val}</option>
                            </aura:iteration>
                            </lightning:select>
                        </td>
                        <td>
    
                            <lightning:select name="Operational Area"
                                    value="{!OperationalAPProver.selectedOperationArea}"
                                              tabindex="{!rowIndex}"
                                              onchange="{!c.opeArea}"                                              
                                              >
    
                            <aura:iteration items="{!v.listSubDependingValues}" var="val">
                                 <option value="{!val}">{!val}</option>
                             </aura:iteration>
                            </lightning:select>
  • I want to create dependent picklist having three dependent columns and it should applies independently on multiple rows. It means picklist fields in Columns are dependent but picklist fields in rows are not dependent to each other .I use the code given in http://sfdcmonkey.com/2018/08/31/dependent-picklist-lightningselect-lightning-salesforce/ , but it makes rows also dependent on each other. Please help if any one has code for this.

    The following is my  code component:

    <aura:iteration items=”{!v.NewoperationalApproverData}” var=”OperationalAPProver” indexVar=”rowIndex”>
    <tr class=”slds-text-title_caps”>
    <td>

    {!rowIndex + 1}

                            <lightning:select name="Division"
                                    value="{!OperationalAPProver.selectedProdDiv}"
                                    tabindex="{!rowIndex}"
                                    onchange="{!c.onControllerFieldChange}" label="{!rowIndex}">
                            <aura:iteration items="{!v.listControllingValues}" var="val">
                                <option value="{!val}">{!val}</option>
                            </aura:iteration>
                            </lightning:select>
                        </td>                    
                        <td>
    
                            <lightning:select name="LO"
                                    value="{!OperationalAPProver.selectedLo}"
                                    tabindex="{!rowIndex}"
    
                                    onchange="{!c.onSubControllerFieldChange}">
                            <aura:iteration items="{!v.listDependingValues}" var="val">
                                <option value="{!val}">{!val}</option>
                            </aura:iteration>
                            </lightning:select>
                        </td>
                        <td>
    
                            <lightning:select name="Operational Area"
                                    value="{!OperationalAPProver.selectedOperationArea}"
                                              tabindex="{!rowIndex}"
                                              onchange="{!c.opeArea}"                                              
                                              >
    
                            <aura:iteration items="{!v.listSubDependingValues}" var="val">
                                 <option value="{!val}">{!val}</option>
                             </aura:iteration>
                            </lightning:select>
  • <option value=“{!val}” selected=”{!val == v.parentValue}”>{!val}</option> – keeps the previous value for the controlling picklist but similar thing doesnt work for the dependent, any suggestions?

    <option value=“{!val}” selected=”{!val == v.childValue}”>{!val}</option> – doesnt work

Leave a Reply