Wednesday 9 May 2018

Salesforce: Making API calls from Lightning Components

We can use REST api in Lightning components by using server side controller, because you can't make API calls from client-side code.

Let's take one example to display weather on your Account records, based on address fields on Account records.

we are going to use the Api to get weather from this URL https://openweathermap.org/api.

Just sign up from this URL to get the weather key. https://home.openweathermap.org/users/sign_up

Once you logged in, click on API Keys tab, like shown below.



It will provide one Default Key, save this Key for future use.

Create Remote site setting in your salesforce org. 

Setup | Security Controls | Remote Site Settings | New

Use this URL http://api.openweathermap.org



Now you are all set to write code.

Create a apex class WeatherController.cls in your salesforce org.



public with sharing class WeatherController {

    private static String apiURL = 'http://api.openweathermap.org/data/2.5/';

    private static String apiKey = 'use your API key ';

    private static String pathCurrentWeather = 'weather?appid='+apiKey+'&units=metric&q=';
    
    // Pass in the endpoint to be used using the string url
    private static String getCalloutResponseContents(String url) {
        String result = null;
        // Instantiate a new http object
        Http h = new Http();
        
        // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
        HttpRequest req = new HttpRequest();
        req.setEndpoint(url);
        req.setMethod('GET');
        
        // Send the request, and return a response
        HttpResponse res = h.send(req);
        if(res.getStatusCode() == 200){
            result = res.getBody();
        }
        return result;
    }

    @AuraEnabled
    public static Object currentWeather(Id recordId) {
        String city;
        if (recordId!=null && recordId.getSobjectType() == Schema.Account.getSObjectType()) {
            Account acc = [Select Id, BillingCity, BillingCountry, BillingLongitude, BillingLatitude from Account WHERE Id=:recordId];
            if (acc!=null) {
                city= acc.BillingCity+' ,'+acc.BillingCountry;
            }
        }
        else if (recordId.getSobjectType() == Schema.Contact.getSObjectType()) {
            Contact con = [Select Id, MailingCity, Mailingcountry from Contact WHERE Id=:recordId];
            if (con!=null) {
                city= con.MailingCity+' ,'+con.MailingCity;
            }
        }
        String weatherUrl = apiURL + pathCurrentWeather + city;
        System.debug('weatherUrl::' + weatherUrl);

        String result = getCalloutResponseContents(weatherUrl);
        System.debug('result::' + result);

        return (result == null)?null:getCalloutResponseContents(weatherUrl);
    }
}


Create Lightning Component:


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" controller="WeatherController" >
    <aura:attribute name="weather" type="Object" />
    <aura:attribute name="message" type="String" />
    <aura:attribute name="title" type="String" />
    <aura:attribute name="severity" type="String" />
    <aura:attribute name="recordId" type="Id" />
    <aura:handler name="init" value="{!this}" action="{!c.getCurrentWeather}" />
    
    <ltng:require styles="{! $Resource.SLDS203 + '/assets/styles/salesforce-lightning-design-system.min.css'}" />
    <div class="slds-grid slds-wrap slds-grid--pull-padded">
        <div class="slds-col--padded slds-size--1-of-1">
            <ui:message class="slds-hide" title="{!v.title}" severity="{!v.severity}" closable="true" aura:id="message">
                {!v.message}
            </ui:message>
            
        </div>
        <div class="slds-col--padded slds-size--1-of-1">
            <aura:if isTrue="{!v.weather != null}">
                <div class="slds-page-header" role="banner">
                    <div class="slds-grid">
                        <div class="slds-col slds-has-flexi-truncate">
                            <div class="slds-media slds-media--center slds-no-space slds-grow">
                                <div class="slds-media__body">
                                    <p class="slds-text-heading--label">City</p>
                                    <h1 class="slds-page-header__title slds-m-right--small slds-truncate slds-align-middle" title="Record Title">
                                        {!v.weather.name},&nbsp;{!v.weather.sys.country}
                                    </h1>
                                </div>
                            </div>
                        </div>
                    </div>
                    <ul class="slds-grid slds-page-header__detail-row">
                        <li class="slds-page-header__detail-block">
                            <p class="slds-text-heading--label-normal slds-truncate slds-m-bottom--xx-small" title="Current">Current</p>
                            <p class="slds-text-body--regular slds-truncate">{!v.weather.main.temp}&deg;C</p>
                        </li>
                        <li class="slds-page-header__detail-block">
                            <p class="slds-text-heading--label-normal slds-truncate slds-m-bottom--xx-small" title="Minimum">Minimum</p>
                            <p class="slds-text-body--regular slds-truncate">{!v.weather.main.temp_min}&deg;C</p>
                        </li>
                        <li class="slds-page-header__detail-block">
                            <p class="slds-text-heading--label-normal slds-truncate slds-m-bottom--xx-small" title="Minimum">Maximum</p>
                            <p class="slds-text-body--regular slds-truncate">{!v.weather.main.temp_max}&deg;C</p>
                        </li>
                        <li class="slds-page-header__detail-block">
                            <p class="slds-text-heading--label-normal slds-truncate slds-m-bottom--xx-small" title="Longitude">Longitude</p>
                            <p class="slds-text-body--regular slds-truncate">{!v.weather.coord.lon}</p>
                        </li>
                        <li class="slds-page-header__detail-block">
                            <p class="slds-text-heading--label-normal slds-truncate slds-m-bottom--xx-small" title="Latitude">Latitude</p>
                            <p class="slds-text-body--regular slds-truncate">{!v.weather.coord.lat}</p>
                        </li>
                        <li>
                        <img src="{!$Resource.weather}" style="max-width:30%"></img>
                        </li>
                    </ul>
                </div>
                
            </aura:if>
        </div>
    </div>
</aura:component>

Javascript controller:



({

getCurrentWeather : function(component, event, helper) {

//var city = component.find('city').get('v.value');

helper.getCurrentWeather(component, helper,event);
}
})



Helper:



({

getCurrentWeather : function(component, helper, city) {

var action = component.get('c.currentWeather');

//action.setParams({"city": city});
        action.setParams({recordId:component.get("v.recordId")});
action.setCallback(this, function(response) {
var state = response.getState();

if (state === "SUCCESS") {
var result = response.getReturnValue();
console.log(result);
if(result != null){
result = JSON.parse(result);
if(result.cod == 200){
component.set('v.weather', result);
}else{
helper.message(component, 'Error!', 'error', result.message);
}
}else{
helper.message(component, 'Error!', 'error', 'Some error occured while getting weather data');
}
}else if (state === "INCOMPLETE") {
}else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
helper.message(component, 'Error!', 'error', errors[0].message);
}
} else {
helper.message(component, 'Error!', 'error', 'Unknown Error');
}
}
});
$A.enqueueAction(action);
},
message: function(component, title, severity, message){
component.set('v.message', message);
component.set('v.title', title);
component.set('v.severity', severity);
var ele = component.find('message');
$A.util.removeClass(ele, 'slds-hide');
$A.util.addClass(ele, 'slds-show');
}
})


Execution Time:


Open any Account record in Lightning mode --> Edit page --> Like shown below



Drag and drop your weather Lightning component to header section and don't forget to provide valid Billing address in your account record.

Then your work is done! weather displays in your record like this.



Done

1 comment: