Create a Component to Use in the Lightning App Builder

Though we use Lightning components to display our indicator badges (and in a later step, we even use Lightning Data Service to get record-level data without Apex), that doesn’t mean we don’t have any need for Apex. In fact, we need to use a fair bit of Apex to make our Indicator Badge records available for use in our Lightning components, along with other information.

In this step, we create an object-aware Lightning component, make it available for use in Lightning App Builder, and use Apex to give the component a dynamic, object-aware label.

Create an Indicator Badges Component

  1. Click the gear icon (Gear Icon), then select Developer Console.
  2. In the Developer Console, select File > New > Lightning Component.
  3. Name the component IndicatorBadges, select Lightning Record Page, and select Submit.
  4. Replace the contents of the component with this code:
    <aura:component implements="force:hasRecordId,force:hasSObjectName,flexipage:availableForRecordHome">
      <aura:attribute name="objLabel" type="String" />
      <aura:attribute name="badgeList" type="Object[]"/>
      <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
      <lightning:card iconName="standard:coaching" title="{! v.objLabel +' Indicators'}" class="slds-text-title_caps">
        <div class="slds-p-left--medium slds-p-right--medium">
          <lightning:layout verticalAlign="stretch" horizontalAlign="start" multipleRows="true" pullToBoundary="small">
            <aura:iteration items="{!v.badgeList}" var="thisBadge" aura:id="theList">
              <lightning:layoutItem size="2" padding="horizontal-small">
                <!--put Indicator Badge here-->
              </lightning:layoutItem>
            </aura:iteration>
          </lightning:layout>
        </div>
      </lightning:card>
    </aura:component>
  5. Click File > Save.

Code Highlights:

  • The developer console provides two interfaces when you create a Lightning component and select the Available for Record Pages checkbox (namely, the force:hasRecordId and flexipage:availableForRecordHome interfaces). We've added a third interface force:hasSObjectName, in order to make our component object-aware as well as record-aware.
  • We're using a Lightning base component to create a title and tidy layout for what will eventually be our list of Indicator Badge items. We're giving that component a recognizable icon ("standard:coaching") and a dynamic title, so that users know what kind of indicators they're looking at.

Create the Indicator Badge Controller Class

In our dynamic title, we want to display the name of the object that users expect—and that value, the Label field, isn't provided by the force:hasSObjectName interface (that gives access to the API Name of an object). To access the value of the Label field in our component, we need to use Apex.

  1. In the Developer Console, click File > New > Apex Class.
  2. Name the Apex class INDICATOR_Controller.
  3. Modify the class as follows:
    public class INDICATOR_Controller {
      @AuraEnabled
      public static String getSObjectLabel(String sObjName){
        String label = Schema.getGlobalDescribe().get(sObjName).getDescribe().getLabel();
        return label;
      }
    }
  4. Click File > Save.
  5. Modify the IndicatorBadges component to include a reference to our Apex controller by adding controller="INDICATOR_Controller" access="public" into the first line of the component, before the >.
  6. Your component markup should now look like this:
    <aura:component implements="force:hasRecordId,force:hasSObjectName,flexipage:availableForRecordHome" controller="INDICATOR_Controller" access="public">
      <aura:attribute name="objLabel" type="String" />
      <aura:attribute name="badgeList" type="Object[]"/>
      <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
      <lightning:card iconName="standard:coaching" title="{! v.objLabel +' Indicators'}" class="slds-text-title_caps">
        <div class="slds-p-left--medium slds-p-right--medium">
          <lightning:layout verticalAlign="stretch" horizontalAlign="start" multipleRows="true" pullToBoundary="small">
            <aura:iteration items="{!v.badgeList}" var="thisBadge" aura:id="theList">
              <lightning:layoutItem size="2" padding="horizontal-small">
                <!--Indicator Badge here-->
              </lightning:layoutItem>
            </aura:iteration>
          </lightning:layout>
        </div>
      </lightning:card>
    </aura:component>
  7. Click CONTROLLER in the component palette on the right and replace the contents with this code:
    ({
      doInit : function(component, event, helper) {
        var sObj = component.get("v.sObjectName");
        if(sObj){
          helper.getLabelForRecord(component, sObj);
        }
      },
      //future code here
    })
  8. Click HELPER in the component palette on the right and replace the contents with this code:
    ({
      getLabelForRecord : function(component, sObj){
        var action = component.get("c.getSObjectLabel");
        action.setParams({
          sObjName : sObj
        });
        action.setCallback(this, function(response){
          var state = response.getState();
          if(state === "SUCCESS"){
            var label = response.getReturnValue();
            component.set("v.objLabel", label);
          } else if(state === "ERROR"){
            console.log('Error: ' + JSON.stringify(response.error));
          } else {
            console.log('Unknown problem, state: '+ state + ', error: ' + JSON.stringify(response.error));
          }
        });
        $A.enqueueAction(action);
      },
      //future code here
    })
  9. Click File > Save All.

Code Highlights:

  • We're using "INDICATOR_" as a class name prefix for the Apex supporting our Indicator Badge application and Lightning components. As our code gets more complex (which it will in the next step), this pattern will help keep the ZBS code base organized into clear functional groups.
  • We've updated our Lightning component to be aware of the Apex-based controller by adding the controller= attribute into our markup.
  • Our component's client-side controller has a doInit function that performs a basic sanity check (making sure the component has a valid API name to pass to the server), and then hands off coordination of the call to the server and response handling to the helper. This pattern of keeping the client-side controller more simplistic and handing off complexity to the helper is more typical of production-ready components. We'll see why in our next step.
  • In our Apex controller, getSObjectLabel method uses the API Name of the object, passed in from our Lightning component, to fetch the more user-friendly SObject Label. We get this information by using the Schema class and related methods.
  • Using the value returned by the Schema method not only displays the object name expected by users for both standard and custom objects, it also displays the information in the language determined by that user's locale settings. (If a translated version exists.)

Add Indicator Badges to Pages in Lightning Experience

The last thing we need to do before we move on is to get our in-progress Indicator Badges component onto some record pages in Lightning Experience.

  1. In Salesforce, click the Accounts tab. Click any record name. (If no records appear in the Recently Viewed list, change to the All Accounts list.)
  2. Click the gear icon (Gear Icon), then select Edit Page to open the Lightning App Builder.
  3. Drag the IndicatorBadges custom component from the Lightning Components list to the page and place it in the right column above the Activity and Chatter tabs.
    Account record page in Lightning App Builder
  4. Click Save.
  5. Click Activate.
  6. Click Assign as Org Default, then click Next and then Save.
  7. Click Back to exit Lightning App Builder and return to the record home page.
    Account record detail page
    There! We can see our Indicator Badges component—and that it understands it's supposed to be showing us "Account Indicators". Let's get our component on the pages of another object and see if we notice any changes.
  8. Click the Contacts tab and select any record. (Again, if no records appear in the Recently Viewed list, change to the 'All' list view.)
  9. Repeat steps 2-7.

Huzzah! On our Contact object, we can see the combination of the force:hasSObjectName interface and our Apex code at work, as the component tells us we're looking at "Contact Indicators". (Well, minus the indicators at this moment.) We've enabled our component to behave correctly in different contexts, and begun to use sObject-agnostic design patterns. Pretty nice.

Keep learning for
free!
Sign up for an account to continue.
What’s in it for you?
  • Get personalized recommendations for your career goals
  • Practice your skills with hands-on challenges and quizzes
  • Track and share your progress with employers
  • Connect to mentorship and career opportunities