Salesforce
Fetch a dependent picklist value set for a controlling field in Apex
Building a website or app experience with dependent picklists is a great way to ensure your users are able to enter accurate, consistent data. Recently, I was developing an application for a customer when I encountered a situation where I needed to fetch dependent picklist values for each controlling picklist field. And since Salesforce doesn’t currently offer a way to natively fetch this type of value set, I decided to go the API route.To solve for this, I set out to create a simple way to fetch dependent picklist values for each controlling picklist field in Apex.After reading through the API docs for DescribeSObjectResult, I learned that the picklist entry object has validFor property, which is not accessible through Apex. Instead, it can be accessed through an API. If you serialize the picklist entry to JSON, validFor property should become available. Then, you can deserialize the content into a custom type.
Solution
Create a class that represents a json version to expose validFor property:
Code snippet if you’d like to copy-paste:/* Summary: Entity to represent a json version of a picklist entry* So that the validFor property becomes exposed*/public class MyPickListInfo {public String validFor;}The code below is documented at line level for readability purposes. Here are a few things to know before building the class:
- To prepare for an arbitrary string to SObjectTypeassociation: getGlobalDescribe() gives us a map of String to SObjectTypes.
- To prepare for an arbitrary field to SObjectFieldassociation: For an entity of type SObjectType, we have access to <MyEntity>.getDescribe().fields.getMap();
Code snippet if you’d like to copy-paste:/*Summary : Code snippet to access picklist value set */global static Map<String, List<String>> getGlobalPickList( ) {//Define table name that has picklist value set fieldsString objectName = ‘opportunity’;//Define controlling picklist value fieldString controllingField = ‘category__c’ ;//Define dependent picklist value fieldString dependentField = ‘subcategory__c’ ;//Declare map variable to store list of dependent value for controlling fieldMap<String, List<String>> controllingInfo = new Map<String, List<String>>( ) ;//Get the type being dealt withSchema.SObjectType objType = Schema.getGlobalDescribe( ).get(objectName) ;Schema.DescribeSObjectResult describeResult = objType.getDescribe ( ) ;//Get controlling field valuesSchema.DescribeFieldResult controllingFieldInfo = describeResult.fields.getMap ( ).get (controllingField).getDescribe ( ) ;//Get dependent field valuesSchema.DescribeFieldResult dependentFieldInfo = describeResult.fields.getMap ( ).get (dependentField).getDescribe ( ) ;List<Schema.PicklistEntry> controllingValues = controllingFieldInfo.getPicklistValues ( ) ;List<Schema.PicklistEntry> dependentValues = dependentFieldInfo.getPicklistValues ( ) ;//Get the label for controlling picklist value setFor (Schema.PicklistEntry> currControllingValue : controllingValues) {controllingInfo.put (currControllingValue.getLabel ( ) , new List<String>( ) ) ;}
Code snippet if you’d like to copy-paste://Iterate through the dependent valuesfor (Schema.PicklistEntry currDependentValue : dependentValues) {//get the validForString jsonString = JSON.serialize(currDependentValue) ;MyPickListInfo info = (MyPickListInfo) JSON.deserialize(jsonString,MyPickListInfo.class) ;String hexString = EncodingUtil.convertToHex (EncodingUtil.base64Decode (info.validFor)).toUpperCase ( ) ;Integer baseCount = 0;for (Integer curr : hexString.getChars ( ) ) {Integer val = 0;if (curr >= 65). {val = curr - 65 + 10;} else {val = curr - 48;}if ((val & 8) == 8) { controllingInfo.get (controllingValues[baseCount + 0].getLabel( ) ).add (currDependentValue.getLabel( ) ) ;}if ((val & 4) == 4) { controllingInfo.get (controllingValues[baseCount + 1].getLabel( ) ).add (currDependentValue.getLabel( ) ) ;}if ((val & 2) == 2) { controllingInfo.get (controllingValues[baseCount + 2].getLabel( ) ).add (currDependentValue.getLabel( ) ) ;}if ((val & 1) == 1) { controllingInfo.get (controllingValues[baseCount + 3].getLabel( ) ).add (currDependentValue.getLabel( ) ) ;}baseCount + 4’}}return controllingInfo;}This solution should help you access the global picklist value set directly from Apex. Happy learning! Find out more about Horizontal's Cross-Cloud Salesforce practice here.