Exercise 2Using Base Lightning Components

Objectives

  • Modify Apex to enable Lightning Component access.
  • Retrieve and display data based on search criteria.
  • Leverage Base Lightning Components to create the interface
  • Use the init method to initialize the component
  • Encapsulate functionality into child components
  • Understand lightning:layout

Step 1 - Create the Apex Class Controller

  1. In the Developer Console, choose File > New > Apex Class. Name the class MyPropertyController and then click OK.
  2. Replace the default code with:

     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
             ];
         }
     }
    
  3. Save the file.
  4. Add @AuraEnabled to the findProperties method.
  5. Save the file.
  6. Close the tab in the Developer Console.

Step 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:

     <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>
    
  5. Click CONTROLLER in the right side bar of the Developer Console.
  6. Replace the default code with the following:

     ({
         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);
         }
     })
    
  7. Save the file.

  8. Go back to a Property Record page, click the Setup icon Setup icon and select Edit Page.

  9. Locate the SimilarProperties component under Custom components and drag it onto the page at the top of the right-hand column.

  10. Click Save and then Back.

    The page should now display a list of properties in the same price range.

Screenshot: SimilarProperties Lightning Component.

Step 3 - Create a Child Component

  1. In the Developer Console, select File > New > Lightning Component.
  2. Name the component SimilarProperty and leave all of the checkboxes unchecked.
  3. Add the following on line 2:

     <aura:attribute name="property" type="Property__c" />
     {!v.property.Name}	    
    
  4. Save the file.
  5. Go back to the SimilarProperties.cmp component. Replace {!item.Name} inside the <li> with:

     <c:SimilarProperty property="{!item}" />
    
  6. Save the file and refresh the Property Detail page.

    You shouldn’t notice any change.

Step 4 - Improve the Interface

  1. Replace {!v.property.Name} in the SimilarProperty.cmp with:

     <lightning:recordViewForm aura:id="viewForm" recordId="{!v.property.Id}" objectApiName="Property__c">
         <lightning:outputField fieldName="Name" />
     </lightning:recordViewForm>
    
  2. Save the file and refresh the Property Detail page.

    Screenshot: Similar Properties using lightning recordViewForm

  3. Add the following to the SimilarProperty.cmp after the initial lightning:outputField:

     <lightning:outputField fieldName="Beds__c"/>
     <lightning:outputField fieldName="Baths__c"/>
     <lightning:outputField fieldName="Price__c"/>
     <lightning:outputField fieldName="Status__c"/>
    
  4. Save the file and refresh the Property Detail page.

    Screenshot: Similar Properties using lightning recordViewForm

  5. Replace the four lines of code you just pasted with the following:

     <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>	
    
  6. Save the file and refresh the Property Detail page.

  7. Replace the contents of the <lightning:recordViewForm> with the following:

     <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>	
    
  8. Save the file and refresh the Property Detail page.

    Screenshot: Similar Properties component with lightning:layout

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>