Skip to content

Instantly share code, notes, and snippets.

@anilsomasundaran
Last active September 26, 2020 18:54
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 anilsomasundaran/b2c7302f3dbde80954611f383fe780e7 to your computer and use it in GitHub Desktop.
Save anilsomasundaran/b2c7302f3dbde80954611f383fe780e7 to your computer and use it in GitHub Desktop.
public with sharing class DependentPicklistController {
@AuraEnabled(cacheable = true)
public static List<PicklistValue> getPicklistValues(String objApiName, String controlField, String dependentField){
List<PicklistValue> pickListValues = new List<PicklistValue>();
if(String.isBlank(objApiName) || String.isBlank(controlField) || String.isBlank(dependentField)) {
//return pickListValues;
objApiName = 'Account';
controlField ='Country__c';
dependentField= 'State__c';
//enable the return statement and remove the above static assignment with some valid error value to update the UI
//return;
}
//Identify the sobject type from the object name using global schema describe function
Schema.SObjectType targetType = Schema.getGlobalDescribe().get(objApiName);
//Create an empty object based up on the above the sobject type to get all the field names
Schema.sObjectType objType = targetType.newSObject().getSobjectType();
//fetch the all fields defined in the sobject
Map<String, Schema.SObjectField> objFieldMap = objType.getDescribe().fields.getMap();
//Get the controlling and dependent picklist values from the objFieldMap
List<Schema.PicklistEntry> controlledPLEntries = objFieldMap.get(controlField).getDescribe().getPicklistValues();
List<Schema.PicklistEntry> dependentPLEntries = objFieldMap.get(dependentField).getDescribe().getPicklistValues();
// Wrap the picklist values using custom wrapper class - PicklistValue
for (Schema.PicklistEntry entry : controlledPLEntries) {
PicklistValue picklistValue = new PicklistValue(entry.isActive(), entry.isDefaultValue(), entry.getLabel(), entry.getValue());
pickListValues.add(picklistValue);
}
//ValidFor is an indicator value for the controlling field which is base64 encrypted
//base64 value should be convered to 6bit grouped binary and 1 indicate the controlling field in a certain order
//Also,validFor value only be shown when it is serialized so it should be serialized then deserialized using PicklistValue wrapper class
for(PicklistValue plVal : deserializePLEntries(dependentPLEntries)) {
String decodedInBits = base64ToBits(plVal.validFor);
for(Integer i = 0; i< decodedInBits.length(); i++) {
// For each bit, in order: if it's a 1, add this label to the dependent list for the corresponding controlling value
String bit = decodedInBits.mid(i, 1);
if (bit == '1') {
PicklistValue dependentPLValue = new PicklistValue(plVal.active, plVal.defaultValue, plVal.label, plVal.value);
//Dependent picklist value is mapped to its parent controlling value through 'dependents' attribute in the PicklistValue wrapper class
if(pickListValues.get(i).dependents == null ) {
pickListValues.get(i).dependents = new List<PicklistValue>{dependentPLValue};
}else{
pickListValues.get(i).dependents.add(dependentPLValue);
}
}
}
}
return pickListValues;
}
private static List<PicklistValue> deserializePLEntries(List<Schema.PicklistEntry> plEntries) {
return (List<PicklistValue>)
JSON.deserialize(JSON.serialize(plEntries), List<PicklistValue>.class);
}
//Available base64 charecters
private static final String BASE_64_CHARS = '' +'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +'abcdefghijklmnopqrstuvwxyz' +'0123456789+/';
// Convert decimal to binary representation (alas, Apex has no native method :-(
// eg. 4 => '100', 19 => '10011', etc.
// Method: Divide by 2 repeatedly until 0. At each step note the remainder (0 or 1).
// These, in reverse order, are the binary.
private 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;
}
// Convert a base64 token into a binary/bits representation
// e.g. 'gAAA' => '100000000000000000000'
private 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 = BASE_64_CHARS.indexOf(thisChar);
String bits = decimalToBinary(val).leftPad(6, '0');
validForBits += bits;
}
return validForBits;
}
//Wrapper class
public class PicklistValue {
@AuraEnabled
public Boolean active { get; set; }
@AuraEnabled
public Boolean defaultValue { get; set; }
@AuraEnabled
public String label { get; set; }
@AuraEnabled
public String validFor { get; set; }
@AuraEnabled
public String value { get; set; }
@AuraEnabled
public List<PickListValue> dependents {get; set;}
public PicklistValue(){}
public PicklistValue(Boolean active, Boolean defaultValue, String label, String validFor, String value) {
this.active = active;
this.defaultValue = defaultValue;
this.label = label;
this.validFor = validFor;
this.value = value;
}
public PicklistValue(Boolean active, Boolean defaultValue, String label, String value) {
this.active = active;
this.defaultValue = defaultValue;
this.label = label;
this.validFor = validFor;
this.value = value;
}
public PicklistValue(String label, String value) {
this.label = label;
this.value = value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment