Create an Indicator Badge Apex Service

We've got our component up and running in Lightning Experience, and an Apex controller connected to it. Now we need to connect our component to our custom metadata—and we'll do that by adding a service in Apex and connecting it with the code we've already written.

Create the Indicator Badge Service class

  1. Click the gear icon (Gear Icon), then select Developer Console.
  2. Click File > New > Apex Class.
  3. Name the Apex class INDICATOR_Service.
  4. Replace the generated code with:
    public class INDICATOR_Service {
      public static List<String> getFieldsToQueryForObject(String objName){
        Set<String> targetFields = new Set<String>();
        for(Indicator_Badge__mdt i: [SELECT Related_Field__r.QualifiedApiName FROM Indicator_Badge__mdt WHERE Object__r.QualifiedApiName = :objName]){
        return new List<String>(targetFields);
      public static List<Indicator> getIndicatorBadgesForObject(SObject sobj){
        List<Indicator> recordIndicators = new List<Indicator>();
        for(Indicator_Badge__mdt indicator: [SELECT MasterLabel, Badge_Color__c, Comparison_Value__c, Comparison_Type__c, Badge_Icon_Name__c, Related_Field__r.QualifiedApiName FROM Indicator_Badge__mdt WHERE Object__r.QualifiedApiName = :sobj.getSObjectType().getDescribe().getName()]){
          recordIndicators.add(evaluateIndicator(indicator, sobj));
        return recordIndicators;
      private static Indicator evaluateIndicator(Indicator_Badge__mdt i, SObject sobj){
        Object field = sobj.get(i.Related_Field__r.QualifiedApiName);
        Boolean isEnabled = false;
        if(i.Comparison_Type__c == 'Use Boolean Value of Field'){
          isEnabled = (Boolean)field;
        } else if(i.Comparison_Type__c == 'Contains'){
          isEnabled = (String.valueOf(field)).contains(i.Comparison_Value__c);
        } else if(i.Comparison_Type__c == 'Not Blank or Null'){
          isEnabled = String.isNotBlank(String.valueOf(field));
        } else if(i.Comparison_Type__c == 'Blank or Null'){
          isEnabled = String.isBlank(String.valueOf(field));
        } else if(i.Comparison_Type__c == 'Greater or Equal'){
          isEnabled = (Decimal)field >= Decimal.valueOf(i.Comparison_Value__c);
        } else if(i.Comparison_Type__c == 'Less or Equal'){
          isEnabled = (Decimal)field <= Decimal.valueOf(i.Comparison_Value__c);
          return new Indicator(i.Badge_Icon_Name__c, i.Badge_Color__c, i.MasterLabel);
        } else {
          return null;
      //inner class, creating our 'Indicator' object and attributes
      public class Indicator{
        //first, the attributes:
        public String icon {get; set;}
        public String color {get; set;}
        public String label {get; set;}
        //then, our object:
        public Indicator(String icon, String color, String label){
          this.icon = icon;
          this.color = color;
          this.label = label;
  5. Click File > Save.

Code Highlights:

  • The INDICATOR_Service class is, as the name suggests, a service for querying and processing Indicator Badge records. It also contains an inner class called Indicator, which acts like a custom object in memory. In other words, it exists for as long as someone is viewing a record and working with it, but no longer. No cluttering up the database! This inner class is the actual object our Lightning components use (hence the @auraEnabled annotations).
  • The getIndicatorBadgesForObject method runs a query for Indicator Badge custom metadata records, based upon the sObject type, which is passed in as a parameter.
  • The getFieldsToQueryForObject method assembles fields needed from a particular record in Salesforce, based on the "Related Field" values found on any associated Indicator Badge records.
  • The evaluateIndicator method is where the magic (aka business logic!) happens: it uses values of a particular record to decide if an indicator badge should display.

Add Access to the Indicator Service into the Indicator Controller

  1. In the Developer Console, navigate to the INDICATOR_Controller Apex class.
  2. Replace the current markup with this code:
    public class INDICATOR_Controller {
      private static SObject sobj;
      public static String getSObjectLabel(String sObjName){
        String label = Schema.getGlobalDescribe().get(sObjName).getDescribe().getLabel();
        return label;
      public static List<INDICATOR_Service.Indicator> getIndicators(String recId, String objectName){
        getSObject(recId, objectName);
        if(sobj != NULL){
          List<INDICATOR_Service.Indicator> indicators = INDICATOR_Service.getIndicatorBadgesForObject(sobj);
          return indicators;
        } else {
          return null;
      public static void getSObject(String recId, String objectName){
        List<String> fNames = INDICATOR_Service.getFieldsToQueryForObject(objectName);
        if(fNames.size() > 0){
          String query = 'SELECT Id,'+ String.join(fNames,',')+' FROM '+ objectName +' WHERE Id =\''+ recId +'\' LIMIT 1';
          List<SObject> results = Database.query(query);
          if(results.size() == 1){
            sobj = results[0];
  3. Click File > Save.

Code Highlights:

  • The @AuraEnabled method in our INDICATOR_Controller coordinates the fetching and returning of Indicator objects (the one defined in-memory by our INDICATOR_Service) for a specific record.
  • The getSObject method uses a dynamic query to grab the relevant fields for the record.