1

We are trying to retrieve the dependent picklist values of a picklist field using answer which work fine if they are only controlling field and dependent fields one level. But if the controlling field is also a dependent field it returns wrong picklist values.

In our case, ‘Inventory_Category_Mirror__c’ is controlling field, ‘Inventory_Sub_Category_Mirror__c’ is a dependent field also a controlling field of ‘Inventory_Sub_Category_Qualifier_Mirror__c’. We are trying to access the dependent field values of ‘Inventory_Sub_Category_Mirror__c’.

For the working scenario, the validFor property of dependent picklist values has 4 characters which converted to decimal values based on the code return a proper result, but if the picklist values are both controlling and dependent it return 8 or 12 validFor characters. Not sure what adjustments need to be done in the code for my usecase.

1

Salesforce has recently Introduced "Salesforce UI API" which includes all logic needed to build UI similar to Salesforce's Standard UI.

It includes methods to get dependent picklists values, picklist values based on record type.

It also works even if the controlling field is a dependent picklist for another field.

Source: https://developer.salesforce.com/blogs/2018/01/introduction-salesforce-ui-api.html

https://developer.salesforce.com/docs/atlas.en-us.uiapi.meta/uiapi/ui_api_resources_picklist_values.htm

https://developer.salesforce.com/docs/atlas.en-us.208.0.uiapi.meta/uiapi/ui_api_responses_picklist_values.htm

0

Given solution at that discussion does not work intermittently if you have large set of picklists and dependencies. I had same issue few months back.

Then I had made some tweaks in that class/logic to work more accurately. Here is the code- you can give a try.

public class Dependencies_BitSet {
    public Map < String, Integer > alphaNumCharCodes {
    get;
    set;
    }
    public Map < String, Integer > base64CharCodes {
    get;
    set;
    }

    public Dependencies_BitSet () {
        LoadCharCodes();
    }

    //Method loads the character codes for all letters
    public void LoadCharCodes() {
        alphaNumCharCodes = new Map < String, Integer > {
           'A' => 65,
           'B' => 66,
           'C' => 67,
           'D' => 68,
           'E' => 69,
           'F' => 70,
           'G' => 71,
           'H' => 72,
           'I' => 73,
           'J' => 74,
           'K' => 75,
           'L' => 76,
           'M' => 77,
           'N' => 78,
           'O' => 79,
           'P' => 80,
           'Q' => 81,
           'R' => 82,
           'S' => 83,
           'T' => 84,
           'U' => 85,
           'V' => 86,
           'W' => 87,
           'X' => 88,
           'Y' => 89,
           'Z' => 90
        };
        base64CharCodes = new Map < String, Integer > ();
        //all lower cases
        Set < String > pUpperCase = alphaNumCharCodes.keySet();
        for (String pKey: pUpperCase) {
            //the difference between upper case and lower case is 32
            alphaNumCharCodes.put(pKey.toLowerCase(), alphaNumCharCodes.get(pKey) + 32);
            //Base 64 alpha starts from 0 (The ascii charcodes started from 65)
            base64CharCodes.put(pKey, alphaNumCharCodes.get(pKey) - 65);
            base64CharCodes.put(pKey.toLowerCase(), alphaNumCharCodes.get(pKey) - (65) + 26);
        }
        //numerics
        for (Integer i = 0; i <= 9; i++) {
            alphaNumCharCodes.put(string.valueOf(i), i + 48);
            //base 64 numeric starts from 52
            base64CharCodes.put(string.valueOf(i), i + 52);
        }
    }

    public List < Integer > testBits(String pValidFor, List < Integer > nList) {
        System.Debug('pValidFor --- '+pValidFor);
        List < Integer > results = new List < Integer > ();
        List < Integer > pBytes = new List < Integer > ();
        Integer bytesBeingUsed = (pValidFor.length() * 6) / 8;
        Integer pFullValue = 0;
        if (bytesBeingUsed <= 1) return results;
        for (Integer i = 0; i < pValidFor.length(); i++) {
            pBytes.Add((base64CharCodes.get((pValidFor.Substring(i, i + 1)))));
        }
        for (Integer i = 0; i < pBytes.size(); i++) {
            Integer pShiftAmount = (pBytes.size() - (i + 1)) * 6; //used to shift by a factor 6 bits to get the value
            pFullValue = pFullValue + (pBytes[i] << (pShiftAmount));
        }

        Integer bit;
        Integer targetOctet;
        Integer shiftBits;
        Integer tBitVal;
        Integer n;
        Integer nListSize = nList.size();
        for (Integer i = 0; i < nListSize; i++) {
            n = nList[i];
            bit = 7 - (Math.mod(n, 8));
            targetOctet = (bytesBeingUsed - 1) - (n >> bytesBeingUsed);
            shiftBits = (targetOctet * 8) + bit;
            tBitVal = ((Integer)(2 << (shiftBits - 1)) & pFullValue) >> shiftBits;
            if (tBitVal == 1)
            results.add(n);
        }
        System.Debug('>>>>>>>> '+pValidFor+' ------ '+results);
        return results;
    }
}

And use this helper class as below AND update field names/label as per your org.

Dependencies_BitSet clsObj  = new Dependencies_BitSet();

Map<String,List<String>> objResults = new Map<String,List<String>>();
        List<Schema.PicklistEntry> contrEntries = objFieldMap.get(controllingField).getDescribe().getPicklistValues();
        List<Schema.PicklistEntry> depEntries = objFieldMap.get(dependentField).getDescribe().getPicklistValues();

        List<Integer> controllingIndexes = new List<Integer>();
        for(Integer contrIndex=0; contrIndex<contrEntries.size(); contrIndex++){            
            Schema.PicklistEntry ctrlentry = contrEntries[contrIndex];
            String label = ctrlentry.getLabel();
            objResults.put(label,new List<String>());
            controllingIndexes.add(contrIndex);
        }
        List<Schema.PicklistEntry> objEntries = new List<Schema.PicklistEntry>();
        List<PicklistEntryWrapper> objJsonEntries = new List<PicklistEntryWrapper>();
        for(Integer dependentIndex=0; dependentIndex<depEntries.size(); dependentIndex++){            
               Schema.PicklistEntry depentry = depEntries[dependentIndex];
               objEntries.add(depentry);
        } 

        objJsonEntries = (List<PicklistEntryWrapper>)JSON.deserialize(JSON.serialize(objEntries), List<PicklistEntryWrapper>.class);
        List<Integer> indexes;
        for (PicklistEntryWrapper objJson : objJsonEntries){
            if (objJson.validFor==null || objJson.validFor==''){
                continue;
            }
            System.Debug('objJson ------ '+controllingIndexes.Size());
            System.Debug(objJson);
            indexes = clsObj.testBits(objJson.validFor,controllingIndexes);
            for (Integer idx : indexes){                
                String contrLabel = contrEntries[idx].getLabel();
                objResults.get(contrLabel).add(objJson.label);
                System.Debug('contrLabel '+ contrLabel +' ---- '+objResults.get(contrLabel));
            }
        }

        **return objResults;  // HOLDS FIELD DEPENDENCIES**
  • 1
    It is working for the first level (controlling - dependent) but if the dependent field is in turn a controlling field of another picklist, it does not work. Any thoughts? – Praveen May 11 '18 at 13:34
  • I've never tried ...Let me try out that,. – Ayub May 11 '18 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.