Building Context-Aware Lightning Components

Lightning Components and App Builder offer new and exciting capabilities for application composition on the platform. For example, you can now edit a page layout in App Builder and add Lightning Components to provide additional information or tools to the page (pilot feature in Winter 16). For these components to be useful, they need to be aware of the context. In other words, they should know which record the page is currently showing.

Fortunately, the Lightning Component Framework makes it really easy to inject the current context into a component. All you need to do is:

  1. Implement the force:hasRecordId interface. For example:
    <aura:component controller="WeatherController"
        implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId">
    
    • The force:appHostable interface indicates the component can be hosted in the Salesforce1 Mobile app
    • The flexipage:availableForAllPageTypes interface indicates the component can be used in App Builder
    • The force:hasRecordId interface indicates the current record Id should be injected in the component’s recordId attribute
  2. Define a recordId attribute as follows:
    <aura:attribute name="recordId" type="Id" />
    

When the component is instantiated on the page, the current record Id is automatically injected in the recordId attribute. You can then make calls to the server passing the recordId as a parameter to retrieve or save data for that specific record.

As an example, I modified the Weather component I shared a few months ago. You can drop the new version in the Account page layout and it will automatically show the weather for the current account based on the account’s billing zip code.

Source Code

Component

<aura:component controller="WeatherController"
    implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId">

    <!-- Id of the Account the page hosting this component is showing -->
    <aura:attribute name="recordId" type="Id" />

    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <!-- The current weather and forecast objects returned by the WeatherUnderground service -->
    <aura:attribute name="currentWeather" type="Object"/>
    <aura:attribute name="forecast" type="Object"/>

    <div>
        <img src="{!v.currentWeather.icon_url}">
        <div class="location">{!v.currentWeather.display_location.full}</div>
        <div class="description">{!v.currentWeather.weather}</div>
        <div class="temperature deg">{!v.currentWeather.temp_f}</div>
        <table>
            <aura:iteration items="{!v.forecast.simpleforecast.forecastday}" var="item">
                <tr valign="middle">
                    <td>{!item.date.weekday}</td>
                    <td></img></td>
                    <td>{!item.conditions}</td>
                    <td class="right-align deg">{!item.high.fahrenheit}</td>
                    <td class="right-align subtle deg">{!item.low.fahrenheit}</td>
                </tr>
            </aura:iteration>
        </table>
    </div>

</aura:component>

Client-Side Controller

({
    doInit : function(component, event, helper) {
        // Get a reference to the getWeather() function defined in the Apex controller
		var action = component.get("c.getAccountWeather");
        action.setParams({
            "accountId": component.get("v.recordId")
        });
        // Register the callback function
        action.setCallback(this, function(response) {
            var data = JSON.parse(response.getReturnValue());
            // Set the component attributes using values returned by the API call
            if (data.current_observation) {
                component.set("v.currentWeather", data.current_observation);
                component.set("v.forecast", data.forecast);
            }
        });
        // Invoke the service
        $A.enqueueAction(action);
    }
    
})

Component Style

.THIS {
    text-align: center;
	left: 0;
    right: 0;
    height: 340px;
    font-weight: 300;
}

.THIS .location {
    font-size: 1.5rem;
	text-transform: uppercase;
}

.THIS .temperature {
    font-size: 3.5rem;
}

.THIS .description {
  	text-transform: uppercase;
    margin: 0.5rem 0 0 0;
}

.THIS table {
    font-size: 0.9rem;
    margin: 1rem auto;
}

.THIS td {
    padding: 0.3rem;
    text-align: left;
    vertical-align: middle;
}

.THIS .right-align {
    text-align: right;
}

.THIS .subtle {
    color: #999999;
}

.THIS td img {
    height: 1.6rem;
    vertical-align: middle;
}

.THIS .deg:not(:empty):after {
    content: '°';
}

Component Design

<design:component label="Weather">
</design:component>

Apex Controller

public with sharing class WeatherController {

    static String baseURL = 'http://api.wunderground.com/api/';
    
    // Sign up for an API key here: http://www.wunderground.com/weather/api/d/login.html
    static String apiKey = 'YOUR_API_KEY';
    
    @AuraEnabled
    public static String getAccountWeather(Id accountId) {
	try {
            Account account = [SELECT BillingPostalCode FROM Account WHERE Id=:accountId];
            String zip = account.BillingPostalCode;
            String url = baseURL + apiKey + '/conditions/forecast/q/' + zip + '.json';
            HttpRequest req = new HttpRequest();
            Http http = new Http();
            req.setMethod('GET');    
            req.setEndpoint(url);
            HTTPResponse res = http.send(req);
            return res.getBody();        	
        } catch(Exception ex){
            return '{"error": "' + ex.getMessage() + '"}';
        }
    }
}

Installation Instructions

Step 1: Defining the Weather Component in your org

  1. Create the different parts of the Weather component as defined above: component, controller, style, design.
  2. Create the WeatherController Apex class as defined above.
  3. Sign up for a free Weather Underground API key.
  4. In the WeatherController class, replace YOUR_API_KEY with your actual Weather Underground API key, and save the file.
  5. In Setup, select Administer > Security Controls > Remote Site Settings, click New Remote Site, specify WeatherUnderground as the Remote Site Name and http://api.wunderground.com as the Remote Site URL. Click Save.

Step 2: Enable Lightning Components

  1. Define a domain (Setup > My Domain) to enable Lightning Components. More information here. Don’t forget to go back to Setup > My Domain after the domain has been activated, and click the Deploy for All Users button.
  2. In Setup, select Lightning App Builder, check the Enable App Builder for Lightning Experience checkbox, and click Save.
  3. In Setup, click Lightning Experience at the top of the left navigation, and switch the toggle to enable the Lightning Experience.
  4. Login to your org again.
  5. In the header, click the down arrow next to your name, and select Switch to Lightning Experience.
  6. Follow the instructions in the video to use the Weather component in App Builder. Make sure you use an account that has a Billing Zip Code specified.

Leave your comments...

Building Context-Aware Lightning Components