wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

By Date: August 2018

Adding Labels to Lightning Datatable


In Part 1 I described a way to make any SOQL result fit for use in a Datatable. The next step is to provide column labels. While it would be easy to just hardcode them, Abhishek suggested to use the original field names. The beauty of that approach: The admin can adjust and/or translate field labels without touching the code.

Going Meta

APEX has a rich API that allow querying an object's properties in the Schema name space. Getting the information for a collection of objects can be done using Schema.describeSObjects(sObjectTypes) or Schema.getGlobalDescribe() (see details here).

The interesting challenge is to find the object names of the relationships, the default field list will only tell you the name you gave it, but not the object you relate to. So some more code is required (see below).

Relationship fields can be identified by the part before the . either ending in __r or id. So we break a query apart and extract a List<String> for the field name and a String for the start object name. Our scenario doesn't cater to subqueries. These two parameters get fed into a utility function.

public without sharing class AuraLabelHelper {
    
    private static Map<String, Schema.SObjectType> globalDescribe = Schema.getGlobalDescribe();
    
    public static Map<String, String> retrieveFieldLablesFromFieldList(List<String> fieldList, String objName) {
        Map<String, String> result = new Map<String, String> ();
        Map<String, Schema.SObjectField> fieldDefinitions = internalFieldLablesFromFieldList(fieldList, objName, '');
        for (String key : fieldDefinitions.keySet()) {
            DescribeFieldResult dfr = fieldDefinitions.get(key).getDescribe();
            result.put(key, dfr.getLabel());
        }
        return result;
    }
    
    
    private static Map<String, Schema.SObjectField> internalFieldLablesFromFieldList(List<String> fieldList, String objName, String prefix) {
        Map<String, Schema.SObjectField> result = new Map<String, Schema.SObjectField> ();
        Schema.SObjectType objectType = AuraLabelHelper.globalDescribe.get(objName);
        Schema.DescribeSObjectResult describeResult = objectType.getDescribe();
        // Labels for the top level object - needs to be lowercased  
        Map<String, Schema.SObjectField> fieldMap = describeResult.fields.getMap();
        Map<String, Schema.SObjectField> fieldMapLower = new Map<String, Schema.SObjectField> ();
        
        for (String key : fieldMap.keySet()) {
            fieldMapLower.put(key.toLowerCase(), fieldMap.get(key));
        }
        
        for (String fieldName : fieldList) {
            String fieldNameLower = fieldName.toLowerCase();
            if (fieldMapLower.containsKey(fieldNameLower)) {
                result.put(prefix + fieldNameLower, fieldMapLower.get(fieldNameLower));
            } else if (fieldNameLower.contains('__r.')) {
                // We have a potential relationship field at hand
                String relationFieldName = fieldNameLower.left(fieldNameLower.indexOf('__r.')) + '__c';
                Schema.DescribeFieldResult relationDescribe = fieldMapLower.get(relationFieldName).getDescribe();
                Schema.SObjectType reference = relationDescribe.getReferenceTo().get(0);
                String objApiName = reference.getDescribe().getName();
                List<String> subFieldList = new List<String> ();
                String newPrefix = prefix + fieldNameLower.left(fieldNameLower.indexOf('.'))+'_';
                subFieldList.add(fieldNameLower.substring(fieldNameLower.indexOf('__r.') + 4));
                result.putAll(internalFieldLablesFromFieldList(subFieldList, objApiName, newPrefix));
            }
        }
        
        return result;
    }
}

Good boys and girls create a test class:

@IsTest
public class AuraLabelHelperTest {

    @IsTest
    public static void simpleAccountTest() {
        List<String> fieldNames = new List<String> ();
        fieldNames.add('Id');
        fieldNames.add('Name');
        fieldNames.add('Customer__c');
        fieldNames.add('Customer__r.Name');

        Map<String, String> result = AuraLabelHelper.retrieveFieldLablesFromFieldList(fieldNames, 'Address__c');
        System.debug(result);
        System.assert(result.containsKey('id'));
        System.assert(result.containsKey('customer__r_name'));

    }

}

Next stop is putting it all together. As usual YMMV.


Posted by on 31 August 2018 | Comments (0) | categories: JavaScript Lightning Salesforce

Lightning Datatable and Relationship Queries


The Lightning Datatable is a flexible component to show data in a sortable, actionable table. Formatting is automatic provided by the Lightning Design System. Data gets provided as JSON array.

The challenge

A prime use case for a data table is to show results returned via @AuraEnabled from a SOQL query. Ideally relationship identity fields should turn into links and data from relationship queries (something like MyCustomObj__r.Color) should be usable in the table as well.

The tricky part: Relationship fields are returned (IMHO properly) as JSON objects. Datatable can't deal with object values for their columns. A returned value might look like this (deliberately using a generic example):

[{
  Id: 'payloadid',
  Color__: 'Blue',
  Stuff__r: {
    Id: 'ToyId',
    Name: 'Teddy',
    Price__c: 34.5,
    Shape__r: {
      Size__c: 'XL',
      Geometry__c: 'round'
    }
  },
  Dance__c: 'Tango'
}];

Read more

Posted by on 29 August 2018 | Comments (1) | categories: JavaScript Lightning Salesforce