Start tracking your progress
Trailhead Home
Trailhead Home

Use Base Lightning Components

Part 1: Create the Apex Class Controller

Our component is going to need data from Salesforce and should allow our Salesforce admin to determine what to search for by defining search criteria when the component is added to the page. So let's get this show started by creating a new Apex class that will accept search criteria.

  1. In the Developer Console, choose File > New > Apex Class. Name the class MyPropertyController and then click OK.
  2. Replace the default code with:
  3. public with sharing class MyPropertyController {
    
        public static List<Property__c> findProperties (Id recordId, Decimal priceRange) {
            List<Property__c> property = [SELECT Price__c FROM Property__c WHERE Id=:recordId];
            Decimal propertyPrice = property[0].Price__c;
            List<Property__c> similarProperties = getSimilarProperties(recordId, priceRange, propertyPrice);
            return similarProperties;
        }
    
        private static List<Property__c> getSimilarProperties (Id recordId, Decimal priceRange, Decimal price ) {
            Decimal range;
            if (priceRange == null) {
                range = 100000;
            } else {
                range = priceRange;
            }
            return [
                SELECT Id, Name, Beds__c, Baths__c, Price__c, Broker__c, Status__c, Thumbnail__c
                FROM Property__c WHERE Id != :recordId AND Price__c > :price - range AND Price__c < :price + range
            ];
        }
    }
    

    The findProperties method takes two parameters: recordId and priceRange. The recordId is for the current Property record. The method then uses these parameters to determine the property price. Then, the three parameters recordId, priceRange, and propertyPrice are passed to the getSimilarProperties method, which returns a list of similar properties.


  4. Save the file.
  5. Add @AuraEnabled to the second line of the Apex class.

  6. The @AuraEnabled signature instructs the class to allow this method to be called from a Lightning component. All methods called from a Lightning component must also be declared as static.


  7. Save the file.
  8. Close the tab in the Developer Console.

Part 2: Create the Similar Properties Component

  1. In the Developer Console, select File > New > Lightning Component.
  2. Name the component SimilarProperties, select Lightning Record Page, and then click Submit.
  3. Add controller="MyPropertyController" to the <aura:component> tag.
  4. Paste the following code into your new component inside the <aura:component> tag.
  5. <aura:attribute name="recordId" type="Id"/>
    <aura:attribute name="similarProperties" type="Object[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <lightning:card iconName="custom:custom85" title="Similar Properties">
        <div class="slds-p-left_medium slds-p-right_medium">
            <ul class="slds-list_vertical slds-has-dividers_top-space">
                <aura:iteration items="{!v.similarProperties}" var="item">
                    <li class="slds-list__item">
                        {!item.Name}
                    </li>
                </aura:iteration>
            </ul>
        </div>
    </lightning:card>
    

    Notice the <aura:attribute> declaration.


    Because we selected Lightning Record Page, the component also uses the force:hasRecordId interface, which automatically retrieves the Id of the current Record page and stores it in the <aura:attribute> with a name of recordId.


    Next, we have an attribute named similarProperties that stores the properties returned by the Apex class. This takes the form of a JSON, so its type is set to Object[].


    The UI of the component is made up of a Base Lightning Component called <lightning:card>. The card uses an icon from SLDS named custom85. Surprise, that’s a real estate sign! Within the body of the card, notice an unordered list <ul> that contains a list item <li>. The unordered list iterates through an array of similarProperties and outputs a list item <li> for each one of the entries in the array. The component uses <aura:iteration> to loop through the records in the similarProperties attribute, and for each record, it displays the name {!item.Name} of the property.


    Finally, when the component loads, the doInit function is called in the component's controller. So, we need to create that function.


  6. Click CONTROLLER in the right sidebar of the Developer Console.
  7. Replace the default code with the following.
  8. ({
        doInit : function(component, event, helper) {
            var action = component.get("c.findProperties");
            action.setParams({
                recordId: component.get("v.recordId"),
                priceRange: "100000"
            });
            action.setCallback(this, function(response){
                var similarProperties = response.getReturnValue();
                component.set("v.similarProperties", similarProperties);
            });
            $A.enqueueAction(action);
        }
    })
    
  9. Save the file.
  10. Go back to a Property Record page, click the Setup icon Setup icon and select Edit Page.
  11. Locate the SimilarProperties component under Custom components and drag it onto the page at the top of the right-hand column.
  12. Click Save and then Back.
  13. The page should now display a list of properties in the same price range.

Part 3: Create a Child Component

When building Aura components, you can put all of the markup into a single component. However, a better practice is to break things up into smaller components to be included in the larger component. This means that these sub-components can also be used in other components.

For this step, we create a component to display more info about each record.

  1. In the Developer Console, select File > New > Lightning Component.
  2. Name the component SimilarProperty and leave all of the checkboxes unchecked.
  3. Click the Submit button.
  4. Add the following on line 2.
  5. <aura:attribute name="property" type="Property__c"/>
    {!v.property.Name}
    
  6. Save the file.
  7. Go back to the SimilarProperties.cmp component. Replace {!item.Name} inside the <li> with:
  8. <c:SimilarProperty property="{!item}"/>
    
  9. Save the file and refresh the Property Detail page. You shouldn’t notice any change.

Part 4: Improve the Interface

  1. Replace {!v.property.Name} in the SimilarProperty.cmp with:
  2. <lightning:recordViewForm aura:id="viewForm" recordId="{!v.property.Id}" objectApiName="Property__c">
        <lightning:outputField fieldName="Name"/>
    </lightning:recordViewForm>
    

    To improve the user interface of our child component we use the lightning:recordViewForm wrapper component. It accepts a record ID and displays fields associated with that record, specified by the lightning:outputField component. In the code above, you specified that the Name field should be displayed.


  3. Save the file and refresh the Property Detail page.
  4. Add the following to the SimilarProperty.cmp after the initial lightning:outputField:
  5. <lightning:outputField fieldName="Beds__c"/>
    <lightning:outputField fieldName="Baths__c"/>
    <lightning:outputField fieldName="Price__c"/>
    <lightning:outputField fieldName="Status__c"/>
    
  6. Save the file and refresh the Property Detail page.
  7. Next, we are going to use lightning:layout, which is a flexible grid system, to arrange the containers in our component. Replace the four lines of code you just pasted with the following.
  8. <lightning:layout multipleRows="true">
        <lightning:layoutItem size="6">
            <lightning:outputField fieldName="Beds__c"/>
        </lightning:layoutItem>
        <lightning:layoutItem size="6">
            <lightning:outputField fieldName="Baths__c"/>
        </lightning:layoutItem>
        <lightning:layoutItem size="6">
            <lightning:outputField fieldName="Price__c"/>
        </lightning:layoutItem>
        <lightning:layoutItem size="6">
            <lightning:outputField fieldName="Status__c"/>
        </lightning:layoutItem>
    </lightning:layout>
    
  9. Save the file and refresh the Property Detail page.
  10. Replace the contents of the <lightning:recordViewForm> with the following.
  11. <div class="slds-media">
        <div class="slds-media__figure">
            <img src="{!v.property.Thumbnail__c}" class="slds-avatar_large slds-avatar_circle" alt="{!v.targetFields.Title_c}"/>
        </div>
        <div class="slds-media__body">
            <lightning:layout class="slds-hint-parent">
                <a onclick="{!c.navToRecord}">
                    <h3 class="slds-text-heading_small slds-m-bottom_xx-small">{!v.property.Name}</h3>
                </a>
            </lightning:layout>
            <lightning:layout multipleRows="true">
                <lightning:layoutItem size="6">
                    <lightning:outputField fieldName="Beds__c"/>
                </lightning:layoutItem>
                <lightning:layoutItem size="6">
                    <lightning:outputField fieldName="Baths__c"/>
                </lightning:layoutItem>
                <lightning:layoutItem size="6">
                    <lightning:outputField fieldName="Price__c"/>
                </lightning:layoutItem>
                <lightning:layoutItem size="6">
                    <lightning:outputField fieldName="Status__c"/>
                </lightning:layoutItem>
            </lightning:layout>
        </div>
    </div>
    
  12. Save the file and refresh the Property Detail page.

Something’s not quite right? Check the code from your components against the following.

MyPropertyController.apxc

public with sharing class MyPropertyController {
    @AuraEnabled
    public static List<Property__c> findProperties (Id recordId, Decimal priceRange) {
        List<Property__c> property = [SELECT Price__c FROM Property__c WHERE Id=:recordId];
        Decimal propertyPrice = property[0].Price__c;
        List<Property__c> similarProperties = getSimilarProperties(recordId, priceRange, propertyPrice);return similarProperties;
    }

    private static List<Property__c> getSimilarProperties (Id recordId, Decimal priceRange, Decimal price ) {
    Decimal range;
    if (priceRange == null) {
        range = 100000;
    } else {
        range = priceRange;
    }
    return [
        SELECT Id, Name, Beds__c, Baths__c, Price__c, Broker__c, Status__c, Thumbnail__c
        FROM Property__c WHERE Id != :recordId AND Price__c > :price - range AND Price__c < :price + range];
    }
}

SimilarProperties.cmp

<aura:component controller="myPropertyController" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global">
    <aura:attribute name="recordId" type="Id"/>
    <aura:attribute name="similarProperties" type="Object[]"/>
    <aura:handler name="init" value="{! this}" action="{!c.doInit}"/>
    <lightning:card iconName="custom:custom85" title="Similar Properties">
        <div class="slds-p-left_medium slds-p-right_medium">
            <ul class="slds-list_vertical slds-has-dividers_top-space">
                <aura:iteration items="{!v.similarProperties}" var="item">
                    <li class="slds-list__item">
                        <c:SimilarProperty property="{!item}"/>
                    </li>
                </aura:iteration>
            </ul>
        </div>
    </lightning:card>
</aura:component>

SimilarPropertiesController.js

({
    doInit : function(component, event, helper) {
        var action = component.get("c.findProperties");
        action.setParams({
            recordId: component.get("v.recordId"),
            priceRange: "100000"
        });
        action.setCallback(this, function(response){
            var similarProperties = response.getReturnValue();
            component.set("v.similarProperties", similarProperties);
        });
        $A.enqueueAction(action);
    }
})

SimilarProperty.cmp

<aura:component >
    <aura:attribute name="property" type="Property__c"/>
    <lightning:recordViewForm aura:id="viewForm" recordId="{!v.property.Id}" objectApiName="Property__c">
        <div class="slds-media">
            <div class="slds-media__figure">
                <img src="{!v.property.Thumbnail__c}" class="slds-avatar_large slds-avatar_circle" alt="{!v.targetFields.Title_c}"/>
            </div>
            <div class="slds-media__body">
                <lightning:layout class="slds-hint-parent">
                    <a onclick="{!c.navToRecord}">
                        <h3 class="slds-text-heading_small slds-m-bottom_xx-small">{!v.property.Name}</h3>
                    </a>
                </lightning:layout>
                <lightning:layout multipleRows="true">
                    <lightning:layoutItem size="6">
                        <lightning:outputField fieldName="Beds__c"/>
                    </lightning:layoutItem>
                    <lightning:layoutItem size="6">
                        <lightning:outputField fieldName="Baths__c"/>
                    </lightning:layoutItem>
                    <lightning:layoutItem size="6">
                        <lightning:outputField fieldName="Price__c"/>
                    </lightning:layoutItem>
                    <lightning:layoutItem size="6"  >
                        <lightning:outputField fieldName="Status__c"/>
                    </lightning:layoutItem>
                </lightning:layout>
            </div>
        </div>
    </lightning:recordViewForm>
</aura:component>