Salesforce UI API Lightning Example

In this blog, I am going to explain how to use Salesforce UI API.Salesforce has the number of APIs to build the native and mobile apps.  Salesforce UI allows you to build native mobile apps and custom web apps. The Great advantage of the Salesforce UI API, you get data and metadata in a single response. You don’t have to worry about layouts, picklists, field-level security, or sharing.

Step 1: Create Connected App 

Create a salesforce connected app as shown below. We need to create a named credential to authenticate the web service call. Go to setup –> create apps–> create a new connected app as shown below and save it to get consumer key and secret key. In this step use any URL as callback URL. later after confirmed the auth provides we will replace the callback URL from auth provider callback URL

After saving the connected app you will get consumer key and consumer secret which we will use to configure the Auth provides.

Step 2: Auth Provider 

Now we need to create an auth provide as shown below. Go to setup –> administration  –> Security control -> create a new Auth provider as shown below .

Replace the connected App callback URL with Auth provide callback URL

Step 3: Named credentials 

Create a named credentials as shown below for authenticating salesforce REST API from the lightning component. 

Code :

Below is the apex class that used to get the data and metadata from the Salesforce UI API.Based on the account selected, you will get the response which contains data and metadata.

public class AuraUIExamples {
    
    @AuraEnabled
    public static List<Account> getAllAccounts(){
        return [Select id, name from Account limit 10];    
    }
    public Map<String, String> uiDisplayList {get;set ; }
    public String accName { get; set; }
    
    public AuraUIExamples(){
        uiDisplayList = new Map<String, String>();
    }
    @AuraEnabled
    public static List<UIDisplay> parseRecord(String accId){
        Http h = new Http();
        
        List<UIDisplay> listRst = new List<UIDisplay>() ;
        
        HttpRequest httpReq = new HttpRequest();
        httpReq.setMethod('GET');
        httpReq.setEndpoint('callout:REST_API1/services/data/v41.0/ui-api/record-ui/'+accId);
        HttpResponse res = h.send(httpReq);
        Map<String, Object> root = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        Map<String, Object> records = (Map<String, Object>)root.get('records');
        Map<String, Object> records1 = (Map<String, Object>)records.get(accId);
        Map<String, Object> records2 = (Map<String, Object>)records1.get('fields');
        for(String keys : records2.keySet()){
            Map<String, Object> sttt = (Map<String, Object>)records2.get(keys) ;
            if((String)sttt.values()[0]!=null){
                System.debug('sttt'+sttt);
                listRst.add(new UIDisplay(keys ,(String)sttt.values()[0] ));
            }
        }
        
        System.debug('listRst'+listRst);
        return listRst ; 
    }
    
    public class UIDisplay {
        @AuraEnabled
        public String label {get;set;}
        @AuraEnabled
        public String value {get;set;}
        public UIDisplay(String label , String value){
            this.label = label ; 
            this.value = value;
        }
        
    }
    
    
}

Create a lightning component Component that will display the data based on the selected account from the drop-down.

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" controller="AuraUIExamples">
    <aura:attribute name="options" type="Account[]" />
    
    <aura:attribute name="result" type="AuraUIExamples.UIDisplay[]" />
    <aura:attribute name="selectedValue" type="String" default=""/>
    <aura:handler name="init" value="{!this}" action="{!c.loadOptions}" />
    <lightning:layout horizontalAlign="center">
        
        <lightning:layoutItem flexibility="auto" padding="horizontal-small">
            <lightning:select name="accountSelect" label="" aura:id="accountSelect" value="{!v.selectedValue}">
                <aura:iteration items="{!v.options}" var="item">
                    <option text="{!item.Name}" value="{!item.Id}" selected="{!item.selected}"/>
                </aura:iteration>
            </lightning:select>
        </lightning:layoutItem>
        <lightning:layoutItem flexibility="auto" padding="around-medium">
            <lightning:button variant="brand" label="Get Selected Account Details" onclick="{! c.getAccountDetails }" aura:id="SearchButton" />
        </lightning:layoutItem>   
    </lightning:layout>
    <lightning:layout horizontalAlign="center">
        
        <table class="slds-table">
            <thead class="headerStyle">
                <tr class="slds-text-title--caps ">
                    <th scope="col">
                        <div class="slds-truncate" title="Label">Label</div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Value">Value</div>
                    </th>
                    
                </tr>
            </thead>
            <tbody>
                <aura:iteration items="{!v.result}" var="obj">
                    <tr>
                        <th scope="row" data-label="Label">
                            <div class="slds-truncate" title="{! obj.label }">{! obj.label }</div>
                        </th>
                        <td data-label="Value">
                            <div class="slds-truncate" title="{! obj.label }">{! obj.value }</div>
                        </td>
                        
                    </tr>
                </aura:iteration>
            </tbody>
        </table>
    </lightning:layout>
    
    
</aura:component>
({
    loadOptions: function (component, event, helper) {
        helper.getAccounts(component);
    },
    getAccountDetails: function (component, event, helper) {
        var accountId = component.find("accountSelect").get("v.value");
        console.log('accountId'+accountId);
        var action = component.get("c.parseRecord");
        action.setParams({
            accId : accountId
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.result", response.getReturnValue());
            }
            else if (state === "INCOMPLETE") {
            }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            console.log("Error message: " + 
                                        errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
        });
        $A.enqueueAction(action);
        
        
    }
})

helper

({
    getAccounts : function(component) {
        var action = component.get("c.getAllAccounts");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.options", response.getReturnValue());
            }
            
            else if (state === "INCOMPLETE") {
                // do something
            }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            console.log("Error message: " + 
                                        errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
        });
        $A.enqueueAction(action);
        
        
        
    },
})

 

.THIS table{
    text-align: center;
    border: solid 1px #86bbc2;
    font: normal 13px Arial, sans-serif;
}
.THIS thead th {
    background-color: #DDEFEF;
    border: solid 1px #DDEEEE;
    padding: 10px;
    text-align: center;
}
.THIS tbody td {
    border: solid 1px #DDEEEE;
    padding: 10px;
}
.THIS tbody tr:nth-child(odd) {
    background-color: #fff;
}
.THIS tbody tr:nth-child(even) {
    background-color: #EEF7EE;
}

 

Salesforce UI API

In this blog, I am going to explain how to use Salesforce UI API.Salesforce has the number of APIs to build the native and mobile apps.  Salesforce UI allows you to build native mobile apps and custom web apps. The Great advantage of the Salesforce UI API, you get data and metadata in a single response. You don’t have to worry about layouts, picklists, field-level security, or sharing.

Step 1: Create Connected App 

Create a salesforce connected app as shown below.  In this post, i am using named credential to authenticate the web service call. Go to setup –> create apps–> create a new connected app as shown below and save it to get consumer key and secret key. In this step use any URL as callback URL. later after confirmed the auth provides we will replace the callback URL from auth provider callback URL

After saving the connected app you will get consumer key and consumer secret which we will use to configure the Auth provides.

Step 2: Auth Provider 

Now we need to create an auth provide as shown below. Go to setup –> administration  –> Security control -> create a new Auth provider as shown below .

Replace the connected App callback URL with Auth provide callback URL

Step 3: Named credentials 

Create a named credentials as shown below for authenticating Salesforce REST API.

Code :

public class UIExamples {
    
    public string accId{get;set;}
    public Map<String, String> uiDisplayList {get;set ; }
    public String accName { get; set; }    
    public List<selectOption> getAccountValues() {
        List<selectOption> options = new List<selectOption>();       
        for(Account a : [Select Id , Name from Account Limit 10 ]){
            options.add(new selectOption(a.Id,a.Name));
        }
        return options;
    } 
    
    public UIExamples(){
        uiDisplayList = new Map<String, String>();
    }
    
    public void parseRecord(){
        Http h = new Http();
        HttpRequest httpReq = new HttpRequest();
        httpReq.setMethod('GET');
        httpReq.setEndpoint('callout:REST_API1/services/data/v41.0/ui-api/record-ui/'+accName);
        HttpResponse res = h.send(httpReq);
        Map<String, Object> root = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        Map<String, Object> records = (Map<String, Object>)root.get('records');
        Map<String, Object> records1 = (Map<String, Object>)records.get(accName);
        Map<String, Object> records2 = (Map<String, Object>)records1.get('fields');
        for(String keys : records2.keySet()){
            Map<String, Object> sttt = (Map<String, Object>)records2.get(keys) ;
            if((String)sttt.values()[0]!=null){
                uiDisplayList.put( keys ,(String)sttt.values()[0]) ;
            }
        }
    }
    
    public class UIDisplay {
        
        public String label {get;set;}
        public String value {get;set;}
        public UIDisplay(String label , String value){
            this.label = label ; 
            this.value = value;
        }
        
    }
    
}

Visualforce page
Create a visualforce page that shows the data and metadata from based on selected account.

<apex:page controller="UIExamples" sidebar="false" showHeader="true" lightningStylesheets="true">
    <apex:slds />
    <apex:form >
        <div align="center">
            <b> Select Account to see the details .</b>
            <apex:selectList size="1" value="{!accName}" >
                <apex:actionSupport event="onchange" action="{!parseRecord}"/>      
                <apex:selectOptions value="{!AccountValues}">
                </apex:selectOptions>
            </apex:selectList>
        </div>
        <br/>
        <div align="center">
            
            
            <apex:pageBlock>
                <apex:pageBlockTable value="{!uiDisplayList}" var="dirKey" columns="2" styleClass="styleHeader" >
                    <apex:column value="{!dirKey}" headerValue="Label" />
                    <apex:column value="{!uiDisplayList[dirKey]}"  headerValue="Value"/>
                </apex:pageBlockTable>
            </apex:pageBlock>
        </div>
    </apex:form>
</apex:page>