Skip to content

Instantly share code, notes, and snippets.

@sfcure
Created May 23, 2019 10:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfcure/4f2c15b3ae4c335e4a74e4dcdfb6afb6 to your computer and use it in GitHub Desktop.
Save sfcure/4f2c15b3ae4c335e4a74e4dcdfb6afb6 to your computer and use it in GitHub Desktop.
Dependent Picklist Based on Record Types
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction"
access="global"
controller="DependentPicklistController">
<!-- Event Handlers -->
<aura:handler name="init" value="this" action="{!c.doInit}"/>
<!-- 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="recordTypeName" type="String" default="" description="store field API name of Controller field"/>
<aura:attribute name="dependingFieldAPI" type="string" default="LightningApps__Country__c" description="store field API name of dependent field"/>
<!--Controller Field-->
<lightning:layoutItem size="4" padding="around-small">
<lightning:select name="controllerFld"
label="Continent"
value="{!v.objDetail.LightningApps__Continent__c}"
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="4" padding="around-small">
<lightning:select name="dependentFld"
label="Country"
value="{!v.objDetail.LightningApps__Country__c}"
disabled="{!v.bDisabledDependentFld}">
<aura:iteration items="{!v.listDependingValues}" var="val">
<option value="{!val}">{!val}</option>
</aura:iteration>
</lightning:select>
</lightning:layoutItem>
</aura:component>
public class DependentPicklistController {
@AuraEnabled
public static Map<String,List<String>> getPicklistValues( String objectName, string fieldName, string recordTypeName ) {
System.debug( 'objectName : ' + objectName );
System.debug( 'fieldName : ' + fieldName );
System.debug( 'recordTypeName : ' + recordTypeName );
if(String.isBlank( objectName) || String.isBlank(fieldName)){
return null;
}
String recordTypeId;
if( !String.isBlank( recordTypeName ) ){
recordTypeId = Schema.getGlobalDescribe().get( objectName ).getDescribe().getRecordTypeInfosByDeveloperName().get( recordTypeName ).getRecordTypeId();
}
if( recordTypeId == null || recordTypeId == '' ){
recordTypeId = Schema.getGlobalDescribe().get( objectName ).getDescribe().getRecordTypeInfosByDeveloperName().get( 'Master' ).getRecordTypeId();
}
Map<String, List<String>> mapPicklistValues = new Map<String, List<String>>();
mapPicklistValues = getValues( objectName, recordTypeId, fieldName );
return mapPicklistValues;
}
public static Map<String, List<String>> getValues(String objectType, String recordTypeId, String fieldName) {
// Create the endpoint dynamically for your og
String Endpoint = URL.getSalesforceBaseUrl().toExternalForm();
endpoint += '/services/data/v45.0';
endpoint += '/ui-api/object-info/' + objectType + '/picklist-values/' + recordTypeId + '/' + fieldName;
EncodingUtil.urlEncode(endpoint,'UTF-8');
// Call the API in order to get the values
HttpRequest req = new HttpRequest();
// Since, we can not use the UserInfo.getSessionId() method here, I am using a Visualforce page in order
// to extract the session id which we can use for making API calls
req.setHeader('Authorization', 'OAuth ' + getSessionIdFromVFPage(Page.SessionId));
req.setHeader('Accept', 'application/json ');
req.setHeader('Content-Type', 'application/json');
req.setEndpoint(endpoint);
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);
Map<String, String> result = new Map<String,String>();
Map<String, List<String>> mapControllingWithDependentList = new Map<String,List<String>>();
Map<Object, String> mapControllingValueWithIndex = new Map<Object,String>();
Map<String, List<String>> mapPicklistValues = new Map<String,List<String>>();
// Parse the response and build the dependent and controlling picklist values map
if( res.getStatus() == 'OK' && res.getStatusCode() == 200 ) {
Map<String,Object> root = (Map<String,Object>) JSON.deserializeUntyped( res.getBody() );
System.debug( ' Response Body : ' + res.getBody() );
// Get all the controlling values from response
if( root.containsKey('controllerValues') ) {
Map<String, Object> controllingValues = (Map<String, Object>) root.get( 'controllerValues' );
// Map of all the controlling values with their index
for( String cValue: controllingValues.keySet() ) {
mapControllingValueWithIndex.put( controllingValues.get(cValue), cValue );
}
}
System.debug('mapControllingValueWithIndex : ' + JSON.serializePretty( mapControllingValueWithIndex ) );
if( !root.containsKey( 'values' ) ){
return mapControllingWithDependentList;
}
// Get all the dependent values from the response returned with the Validfor attribute
// Each bit in the bitmap indicates whether this dependent picklist value is "valid for" a corresponding controlling field value
// The value in the validFor member is a Base64-encoded bitmap.
List<Object> pValues = (List<Object>) root.get( 'values' );
for(Object pValue : pValues) {
Map<String,Object> pValueMap = (Map<String,Object>)pValue;
result.put( (String) pValueMap.get('value'), (String) pValueMap.get('label') );
for(Object validfor : (List<Object>)pValueMap.get('validFor')) {
//Map the dependent Values List with their Controlling Value
if( mapControllingValueWithIndex.containsKey( validfor ) ) {
if( !mapControllingWithDependentList.containsKey( mapControllingValueWithIndex.get( validfor ) ) ) {
mapControllingWithDependentList.put( mapControllingValueWithIndex.get( validfor ), new List<String>() );
}
mapControllingWithDependentList.get( mapControllingValueWithIndex.get( validfor ) ).add( (String) pValueMap.get( 'label' ) );
}
}
}
System.debug( 'mapControllingWithDependentList : ' + JSON.serializePretty( mapControllingWithDependentList ) );
//Map all the controlling values
for( String controllingFields : mapControllingValueWithIndex.Values() ){
//Map controllingFields which has no dependent values associated to it
if( !mapPicklistValues.containsKey( controllingFields ) ) {
mapPicklistValues.put(controllingFields,new List<String>());
}
//Map controllingFields which has dependent values associated to it
if(mapPicklistValues.containsKey( controllingFields ) &&
mapControllingWithDependentList.containsKey( controllingFields ) ) {
mapPicklistValues.get( controllingFields ).addAll( mapControllingWithDependentList.get( controllingFields ) );
}
}
}
else{
System.debug( 'mapPicklistValues : ' + JSON.serializePretty( mapPicklistValues ) );
}
//Return the Map of Controlling fields with the List of Dependent fields on the basis of Record Types
System.debug( 'mapPicklistValues : ' + JSON.serializePretty( mapPicklistValues ) );
return mapPicklistValues;
}
public static String getSessionIdFromVFPage( PageReference visualforcePage ) {
if( !Test.isRunningTest() ) {
String sessionId = visualforcePage.getContent().toString();
return sessionId;
}
return UserInfo.getSessionId();
}
}
({
doInit : function(component, event, helper) {
// get the fields API name and pass it to helper function
var recordTypeName = component.get("v.controllingFieldAPI");
var dependingFieldAPI = component.get("v.dependingFieldAPI");
var objDetails = component.get("v.objDetail");
// call the helper function
helper.fetchPicklistValues(component, objDetails, recordTypeName, dependingFieldAPI );
},
onControllerFieldChange: function(component, event, helper) {
// get selected controller field value
var selectedControllerValue = event.getSource().get("v.value");
var depnedentFieldMap = component.get("v.depnedentFieldMap");
if ( selectedControllerValue != '--- None ---' ) {
let dependentFieldOptions = depnedentFieldMap[selectedControllerValue];
if( dependentFieldOptions.length > 0 ) {
component.set("v.bDisabledDependentFld" , false);
helper.fetchDepValues( component, dependentFieldOptions );
}
else{
component.set("v.bDisabledDependentFld" , true);
component.set("v.listDependingValues", ['--- None ---']);
}
}
else {
component.set("v.listDependingValues", ['--- None ---']);
component.set("v.bDisabledDependentFld" , true);
}
},
})
({
fetchPicklistValues: function( component, objDetails, recordTypeName, dependentField) {
console.log('*********');
// call the server side function
var action = component.get("c.getPicklistValues");
// pass paramerters [object definition , contrller field name , record type name] -
// to server side function
action.setParams({
"objectName" : objDetails.sobjectType,
"fieldName": dependentField,
"recordTypeName": recordTypeName
});
//set callback
action.setCallback(this, function(response) {
if (response.getState() == "SUCCESS") {
// Returned a map
let responseObj = response.getReturnValue();
console.log(responseObj);
// Set the attribute with returned response
component.set( "v.depnedentFieldMap", responseObj );
// Prepare a list of controlling values
let controllerFieldValues = [];
for (var cValue in responseObj ) {
controllerFieldValues.push( cValue );
}
if ( controllerFieldValues.length > 0) {
controllerFieldValues.unshift('--- None ---');
}
// set the controllerFieldValues variable values to continent(controller picklist field)
component.set("v.listControllingValues", controllerFieldValues);
}
else{
alert('Something went wrong..');
}
});
$A.enqueueAction(action);
},
fetchDepValues: function( component, dependentFieldOptions ) {
// create a empty array var for store dependent picklist values for controller field
let dependentFields = [];
dependentFields.push('--- None ---');
for ( let i = 0; i < dependentFieldOptions.length; i++ ) {
dependentFields.push( dependentFieldOptions[i] );
}
component.set( "v.listDependingValues", dependentFields );
},
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment