How to display multilevel dependant picklist in lightning component? For example: Country must control values in State and inturn State must control the values to be displayed in city field. Any help on this will be appreciated!
if you want to create 3 level fields dependency then you need to make some changes in above post :
here is the example with 3 fields dependency..
---- Country ---- City [controller field Country] ----- language [controller field City ]
<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="listSubDependingValues" 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="subDepnedentFieldMap" type="map" description="map to store sub dependent values with controlling value"/>
<aura:attribute name="bDisabledDependentFld" type="boolean" default="true"/>
<aura:attribute name="bDisabledSubDependentFld" 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"/>
<aura:attribute name="subDependingFieldAPI" type="string" default="Language__c" description="store field API name of sub 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}"
onchange="{!c.onSubControllerFieldChange}">
<aura:iteration items="{!v.listDependingValues}" var="val">
<option value="{!val}">{!val}</option>
</aura:iteration>
</lightning:select>
</lightning:layoutItem>
<!--sub Dependent Field-->
<lightning:layoutItem size="12" padding="around-small">
<lightning:select name="subDependentFld"
value="{!v.objDetail.Language__c}"
label="language"
disabled="{!v.bDisabledSubDependentFld}">
<aura:iteration items="{!v.listSubDependingValues}" var="val">
<option value="{!val}">{!val}</option>
</aura:iteration>
</lightning:select>
</lightning:layoutItem>
</aura:component>
js controller
({
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 subDependingFieldAPI = component.get("v.subDependingFieldAPI");
var objDetails = component.get("v.objDetail");
// call the helper function
helper.fetchPicklistValues(component,objDetails,controllingFieldAPI, dependingFieldAPI, "v.depnedentFieldMap");
// 2nd and 3ed picklist
helper.fetchPicklistValues(component,objDetails,dependingFieldAPI, subDependingFieldAPI, "v.subDepnedentFieldMap");
},
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 ---') {
// disable and reset sub dependent field
var ListOfDependentFields = depnedentFieldMap[controllerValueKey];
if(ListOfDependentFields.length > 0){
component.set("v.bDisabledDependentFld" , false);
helper.fetchDepValues(component, ListOfDependentFields,"v.listDependingValues");
}else{
component.set("v.bDisabledDependentFld" , true);
component.set("v.listDependingValues", ['--- None ---']);
}
} else {
component.set("v.listDependingValues", ['--- None ---']);
component.set("v.bDisabledDependentFld" , true);
}
component.set("v.bDisabledSubDependentFld" , true);
component.set("v.listSubDependingValues", ['--- None ---']);
},
onSubControllerFieldChange : function(component, event, helper) {
var controllerValueKey = event.getSource().get("v.value"); // get selected sub controller field value
var depnedentFieldMap = component.get("v.subDepnedentFieldMap");
if (controllerValueKey != '--- None ---') {
var ListOfDependentFields = depnedentFieldMap[controllerValueKey];
if(ListOfDependentFields.length > 0){
component.set("v.bDisabledSubDependentFld" , false);
helper.fetchDepValues(component, ListOfDependentFields,"v.listSubDependingValues");
}else{
component.set("v.bDisabledSubDependentFld" , true);
component.set("v.listSubDependingValues", ['--- None ---']);
}
} else {
component.set("v.listSubDependingValues", ['--- None ---']);
component.set("v.bDisabledSubDependentFld" , true);
}
},
})
js helper :
({
fetchPicklistValues: function(component,objDetails,controllerField, dependentField,mapAttrName) {
// 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(mapAttrName,StoreResponse);
if(mapAttrName == 'v.depnedentFieldMap'){
// 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,lstAttrName) {
// 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(lstAttrName, dependentFields);
},
})
if you want to create 3 level fields dependency then you need to make some changes in above post :
here is the example with 3 fields dependency..
---- Country ---- City [controller field Country] ----- language [controller field City ]
<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="listSubDependingValues" 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="subDepnedentFieldMap" type="map" description="map to store sub dependent values with controlling value"/>
<aura:attribute name="bDisabledDependentFld" type="boolean" default="true"/>
<aura:attribute name="bDisabledSubDependentFld" 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"/>
<aura:attribute name="subDependingFieldAPI" type="string" default="Language__c" description="store field API name of sub 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}"
onchange="{!c.onSubControllerFieldChange}">
<aura:iteration items="{!v.listDependingValues}" var="val">
<option value="{!val}">{!val}</option>
</aura:iteration>
</lightning:select>
</lightning:layoutItem>
<!--sub Dependent Field-->
<lightning:layoutItem size="12" padding="around-small">
<lightning:select name="subDependentFld"
value="{!v.objDetail.Language__c}"
label="language"
disabled="{!v.bDisabledSubDependentFld}">
<aura:iteration items="{!v.listSubDependingValues}" var="val">
<option value="{!val}">{!val}</option>
</aura:iteration>
</lightning:select>
</lightning:layoutItem>
</aura:component>
js controller
({
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 subDependingFieldAPI = component.get("v.subDependingFieldAPI");
var objDetails = component.get("v.objDetail");
// call the helper function
helper.fetchPicklistValues(component,objDetails,controllingFieldAPI, dependingFieldAPI, "v.depnedentFieldMap");
// 2nd and 3ed picklist
helper.fetchPicklistValues(component,objDetails,dependingFieldAPI, subDependingFieldAPI, "v.subDepnedentFieldMap");
},
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 ---') {
// disable and reset sub dependent field
var ListOfDependentFields = depnedentFieldMap[controllerValueKey];
if(ListOfDependentFields.length > 0){
component.set("v.bDisabledDependentFld" , false);
helper.fetchDepValues(component, ListOfDependentFields,"v.listDependingValues");
}else{
component.set("v.bDisabledDependentFld" , true);
component.set("v.listDependingValues", ['--- None ---']);
}
} else {
component.set("v.listDependingValues", ['--- None ---']);
component.set("v.bDisabledDependentFld" , true);
}
component.set("v.bDisabledSubDependentFld" , true);
component.set("v.listSubDependingValues", ['--- None ---']);
},
onSubControllerFieldChange : function(component, event, helper) {
var controllerValueKey = event.getSource().get("v.value"); // get selected sub controller field value
var depnedentFieldMap = component.get("v.subDepnedentFieldMap");
if (controllerValueKey != '--- None ---') {
var ListOfDependentFields = depnedentFieldMap[controllerValueKey];
if(ListOfDependentFields.length > 0){
component.set("v.bDisabledSubDependentFld" , false);
helper.fetchDepValues(component, ListOfDependentFields,"v.listSubDependingValues");
}else{
component.set("v.bDisabledSubDependentFld" , true);
component.set("v.listSubDependingValues", ['--- None ---']);
}
} else {
component.set("v.listSubDependingValues", ['--- None ---']);
component.set("v.bDisabledSubDependentFld" , true);
}
},
})
js helper :
({
fetchPicklistValues: function(component,objDetails,controllerField, dependentField,mapAttrName) {
// 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(mapAttrName,StoreResponse);
if(mapAttrName == 'v.depnedentFieldMap'){
// 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,lstAttrName) {
// 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(lstAttrName, dependentFields);
},
})
This has been really helpful, but I have one problem: when I call helper.fetchPickListValues more than once (as in the js controller code above lines 10-13), an error comes up saying the function does not exist - but only the second time! Has anybody else experienced this or have any ideas what is going on?
http://sfdcmonkey.com/2018/08/31/dependent-picklist-lightningselect-lightning-salesforce/
if you want to create 3 level fields dependency then you need to make some changes in above post :
here is the example with 3 fields dependency..
---- Country
---- City [controller field Country]
----- language [controller field City ]
js controller
js helper :
No need to change in Apex Controller
Thanks , let us know if it helps you
http://sfdcMonkey.com
All Answers
http://sfdcmonkey.com/2018/08/31/dependent-picklist-lightningselect-lightning-salesforce/
if you want to create 3 level fields dependency then you need to make some changes in above post :
here is the example with 3 fields dependency..
---- Country
---- City [controller field Country]
----- language [controller field City ]
js controller
js helper :
No need to change in Apex Controller
Thanks , let us know if it helps you
http://sfdcMonkey.com
Can you share the class of dependentPicklist_UpdateCtrl?
Many thanks
FYI!
http://sfdcmonkey.com/2018/08/31/dependent-picklist-lightningselect-lightning-salesforce/
Regards
Sarah
This has been really helpful, but I have one problem: when I call helper.fetchPickListValues more than once (as in the js controller code above lines 10-13), an error comes up saying the function does not exist - but only the second time! Has anybody else experienced this or have any ideas what is going on?
https://salesforce-lwc-multidependentpicklist.blogspot.com/