1

Here is what I'm trying to do:

I've a record of custom metadata type object. It has only check box type custom fields(around 10). I want to write a function, which will provide me list of fields which are checked, when I pass one of such record to that function.

This is what I've done and working fine but wondering, if there is shortest way:

 // create before-hand map of field name and field details and pass to below function
 private List<string>  findCheckedFields(xyz__mdt record1, Map<String, Schema.SObjectField> fieldMap ){

     List<string> returnList = new list<string>();

     if(record1.abc__c == true )
        returnList.add(fieldMap.get('abc__c').getDescribe().getLabel());
     if(record1.def__c== true )
        returnList.add(fieldMap.get('def__c').getDescribe().getLabel());
     if(record1.efg__c== true )
       --------- and So on ..................
       -------------------------------
       return returnlist;
     }

Problem is, in future, if some new field is added to custom meta data, then I've to modify this method(code) to include check of that field.

I want method, which should be able to check(handle), any new fields added, automatically, without need to modify code.

  • I assume that like normal SObjects you can use describe calls to get the set of fields and base your logic on that e.g. for (SObjectField field : xyz__mdt.getDescribe().fields.getMap().values()) { ... }. – Keith C Apr 9 '17 at 9:41
  • Thanks Keith. Before I could proceed myself on this, Sfdcfox has given wonderful solution – sfdc_Qrius Apr 9 '17 at 21:10
3

Yes, you can create a list of fields and access them dynamically:

List<string> findCheckedFields(xyz__mdt record1) {
    String[] results = new String[0];
    // Get list of fields dynamically
    for(SObjectField field: xyz__mdt.sobjectType.getDescribe().fields.getMap().values()) {
        // We compare any type to true, okay because value must be
        // not-null, a Boolean, and true in order to match.
        if(record1.get(field) == true) {
            results.add(field.getDescribe().getLabel());
        }
    }
    return results;
}

As a matter of performance, consider bulkifying this code so that the describe is not called repeatedly. One possible solution to this might be:

// Store describe information so we initialize only once per transaction.
// We can use SObjectField tokens as keys.
static Map<SObjectField, String> fieldLabels;

List<List<String>> findCheckedFields(xyz__mdt[] records) {
    List<List<String>> results = new List<List<String>>();
    // Lazy-loading: only describe fields once this method is
    // called, and initialize only once.
    if(fieldLabels == null) {
        fieldLabels = new Map<SObjectField, String>();
        for(SObjectField field: xyz__mdt.sobjectType.getDesribe().fields.getMap().values()) {
            fieldLabels.put(field, field.getDescribe().getLabel());
        }
    }
    // For each record
    for(SObject record: records) {
        List<String> recordResults = new List<String>();
        // For each field
        for(SObjectField field: fieldLabels.keySet()) {
            // Compare field value to Boolean true
            if(record.get(field) == true) {
                recordResults.add(fieldLabels.get(field));
            }
        }
        results.add(recordResults);
    }
    return results;
}

The final output of this method will be a list of lists of strings, one for each record, with records having no checked fields returning an empty list.

| improve this answer | |

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.