Day: May 11, 2018

force:recordEdit Example

In this blog, I am going to explain how to use force:recordEdit component to implement the custom edit for any object. A force:recordEdit component represents the record edit UI for the specified recordId.This component display fields in the order they appear on the corresponding page layout and record detail page. This example displays the record edit UI and a button and when button pressed saves the record.

<force:recordEdit aura:id="edit" recordId="a02D0000006V8Ni"/>
<lightning:button label="Save" onclick="{!c.save}"/>

The Example which I am using is here is simply get the record id by using force:hasRecordId interface with overriding the Edit Button on the contact.

Here is the sample code.

<aura:component implements="force:lightningQuickAction,force:hasRecordId,lightning:actionOverride">
    Record save status: {!v.saveState}
    <aura:attribute name="saveState" type="String" default="UNSAVED" />
    <aura:handler name="onSaveSuccess" event="force:recordSaveSuccess" action="{!c.handleSaveSuccess}"/>
    
    <force:recordEdit aura:id="edit" recordId="{!v.recordId}"/>
    
    <lightning:button label="Save" onclick="{!c.save}"/>    
</aura:component>
({
    save : function(component, event, helper) {
        component.find("edit").get("e.recordSave").fire();
    },
    handleSaveSuccess : function(component, event) {
        component.set("v.saveState", "SAVED");
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Success!",
            "message": "The record has been updated successfully."
        });
        toastEvent.fire();
    }
    
})

Code Highlights 

  • force:recordSaveSuccess event is used with onSaveSuccess after the record is successfully updated. Fired when record saving was successful.
  • e.recordSave is used to fire the save event of force:recordEdit

Go to the contact and override the edit button as shown below

Once you click on Edit record you can see now its override force:recordEdit component. 

After the successful update of the record, it will show the toast message as shown below. 

 

Lightning Component Canvas Example

Introduction

In this blog, I am going to explain Heroku and node js canvas integration on lightning experience by using force:canvasApp .

Prerequisites

  1. Git installed on your local machine
  2. Heroku account
  3. Heroku toolbelt installed.
  4. Node.js installed on your local machine

Creating Connected App

In order to integrate the salesforce with Heroku application, you need to create the configure the salesforce connected app.

  • Setup -> Create -> Apps -> Connected Apps-> New
  • Fill  Connected App NameAPI Name, and Contact Email
  • Check the Enable OAuth Settings in the API (Enable OAuth Settings) section
    • Callback URL: add as https://localhost.com/_callback. Later after deploying node js app to Heroku, we need to change this.
    • Selected OAuth Scopes: select the scopes you want for the NodeJS app access token to grant.  Select as ” Full Access ” for this testing app.
  • In the section, Canvas App Settings type Check Force.com Canvas
  • Canvas App URL: https://localhost.com/canvas/callback.Later after deploying the apps Heroku, we are going to change this URL.
  • Access Method: Signed Request (POST)
  • Locations: choose Chatter Tab and publisher as of now. but you can select one or more based on the where you want to show this the canvas on salesforce. Now final connected App is looking as shown below.

Now you need to enable the app for the profiles or users. To do this,

  • Click on the Manage on the connected App which you created in above .click edit policies
  • In the OAuth policies select Admin approved users are pre-authorized for the Permitted Users field and save it
  • In the Profiles related list add the profiles which you wanted to grant access.

Building Your App on Node Js

Let’s set up the basic app structure. We will use Express to set up a basic Node application. Here is the below package.json file which we will use to build the node js application. Application folder structure is shown below.

package.json

use below package.json file

 

  • Once you have created your file structure, set up a Git repo in this directory by running from command. $ git init your command line within this directory.
  • Inside of the public > views > index.html file, add the following code

 

<!DOCTYPE html>
<html lang="en">

<head>

</head>

<body>
<h1> Hello Lightning</h1> 

</body>
</html>
  • From the command line in the main app directory initialize your Node app by running -.npm install which will load all the node modules from the package.json

In the index.js file add the following code:

var express  = require('express'),
  bodyParser = require('body-parser'),
  path       = require('path'),
  CryptoJS   = require("crypto-js");

app        = express(),
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'bower_components')));

app.use(bodyParser.json()); // create application/json parser
app.use(bodyParser.urlencoded({ entended: true })); //create application/x-www-urlencoded parser

var views = path.join(__dirname, 'public/views');
 var   consumerSecret = process.env.CONSUMER_SECRET;

app.get('/', function (req, res) {
  res.sendFile(path.join(views, 'index.html'));
});

app.post('/', function (req, res) {
  // Desk secret key	
  var shared = consumerSecret;
  // Grab signed request
  var signed_req = req.body.signed_request;
  // split request at '.'
  var hashedContext = signed_req.split('.')[0];
  var context = signed_req.split('.')[1];
  // Sign hash with secret
  var hash = CryptoJS.HmacSHA256(context, shared); 
  // encrypt signed hash to base64
  var b64Hash = CryptoJS.enc.Base64.stringify(hash);
  if (hashedContext === b64Hash) {
    res.sendFile(path.join(views, 'index.html'));
  } else {
    res.send("authentication failed");
  };  		
})

var port = process.env.PORT || 9000;
app.listen(port);
console.log('Listening on port ' + port);

Run the following from the command line within your main app directory to push your changes to Heroku.

  1. heroku create
  2. git add .
  3. git commit -m "pushing to heroku"
  4. git push heroku master
  5. heroku open
    Open the URL which looks like  https://shrouded-dawn-91712.herokuapp.com/

Now go to the Connected app which you created in earlier, update the callback URL and Canvas App URL with the Heroku app URL  example https://shrouded-dawn-91712.herokuapp.com. We have to add the environmental variable to the Heroku app with the  Consumer secret from the connected app. Run the below command to set the environmental variable

heroku config:set CONSUMER_SECRET=xxxx

Lightning component

Here is the lightning component that will invoke the canvas app

<aura:component >
    <force:canvasApp developerName="Lightning_Heroku" />
    
</aura:component>

force:canvasApp component represents a canvas app that’s embedded in your Lightning component as shown in the above code.

 

 

aura:iteration

In this blog, I am going to show how to use the aura:iteration to renders a view of a collection of items. aura:iteration iterates over a collection of items and renders the body of the tag for each item. The Below are the different examples to show how you can use iteration.

Simple iteration

In this example, we are iterating over the array of String.

<aura:component>
    <aura:attribute name="items" type="String[]" default="['red','green','blue']"/>
    <aura:iteration items="{!v.items}" var="item">
        <ul>
            <li>{!item}</li>
        </ul>
    </aura:iteration>
</aura:component>

Nested Iteration

The following code nested iteration

<aura:component>
    <aura:attribute name="items" type="String[]" default="['color','color','color']"/>
    <aura:attribute name="innerData" type="String[]" default="['red','green','blue']"/>
    
    <ul>
        <aura:iteration items="{!v.items}" var="outer" indexVar="index">
            <li>{!outer}</li>
            <ul>
                <aura:iteration items="{!v.innerData}" var="inner" indexVar="index">
                    <li>        {!inner}</li>
                </aura:iteration>
            </ul>
            
        </aura:iteration>
    </ul>
    
</aura:component>

Object iteration

The following example shows iteration over the Javascript object

<aura:component>
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
    <aura:attribute name="data" type="Object"/>
    <aura:iteration items="{!v.data}" var="item">
        {!item.fieldName} -- {!item.newValue} <br/>
    </aura:iteration>
</aura:component>
({
    init: function (cmp) {
        var changes = [
            {
                "fieldName": "Name",
                "newValue": "Burlington Co of America",
                "oldValue": "Burlington Corp of America"
            },
            {
                "fieldName": "Revenue",
                "newValue": "$500,000,000.00",
                "oldValue": "$500,000,000.00"
            }
        ];
        cmp.set('v.data', changes);
    }
})

Wrapper Class Iteration

The Following Example shows how to iterate   the wrapper class collections

public with sharing class WrapperController {
    @AuraEnabled
    public static List<WrapperClass> getList() {
        List<WrapperClass> wrapperIns = new List<WrapperClass>();
        for(Integer i=0 ; i<10 ;i++){
            wrapperIns.add(new WrapperClass('Name'+i , 'Value'+i));
        }
        
        return wrapperIns ;
    }
    
    public class WrapperClass{
        public WrapperClass(String name , String value){
            this.name = name ; 
            this.value = value ;
        }
        @AuraEnabled
        public String name {get;set;}
        @AuraEnabled
        public String value {get;set;}
        
        
    }
}
<aura:component controller="WrapperController">
    <aura:attribute name="Wrapper" type="WrapperController[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
    <aura:iteration items="{!v.Wrapper}" var="item">
        {!item.name} -- {!item.value} <br/>
    </aura:iteration>
</aura:component>
({
    init: function (cmp) {
        var action = cmp.get("c.getList");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                cmp.set('v.Wrapper', response.getReturnValue());
            }
        });
        $A.enqueueAction(action);  
    }
})

Server Side Controller 

The following example shows how to iterate the server-side data

public with sharing class ContactController {
    @AuraEnabled
    public static List<Contact> getContacts() {
        return [Select Id, FirstName, LastName, Email, Phone From Contact ];
    }
}
<aura:component controller="ContactController">
    <aura:attribute name="contacts" type="Contact[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
    <aura:iteration items="{!v.contacts}" var="contact">
        {!contact.LastName} -- {!contact.FirstName} <br/>
    </aura:iteration>
</aura:component>
({
    init: function (cmp) {
        var action = cmp.get("c.getContacts");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                cmp.set('v.contacts', response.getReturnValue());
            }
        });
        $A.enqueueAction(action);  
    }
})

Iteration Index

The Following code shows how to get the index of iteration position.

<aura:component>
    
    <aura:attribute name="items" type="List" default="[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]"/>
    <aura:attribute name="setIndexesInInit" type="Boolean" default="true" />
    <aura:attribute name="start" type="Object" default="0"/>
    <aura:attribute name="end" type="Object" default="10"/>
    
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
    
    <aura:iteration aura:id="iteration"
                    items="{!v.items}"
                    var="var"
                    indexVar="idx"
                    start="{!v.start}"
                    end="{!v.end}">
        <ul>
            <li> Index  {!idx} And Value is  {!var}</li>
        </ul>
    </aura:iteration>
    
    
    
</aura:component>

 

 

 

Conditionally Renderings with aura:if

In this blog I am going to show how to use aura:if to conditionally instantiates and renders either the body or the components .aura:if evaluates the isTrue expression on the server and instantiates components in either its body or else attribute. Only one branch is created and rendered any time with if condition. Below is the sample example how it looks like

<aura:component>
    <aura:if isTrue="{!v.truthy}">
    True
    <aura:set attribute="else">
      False
    </aura:set>
  </aura:if> 
</aura:component>

Simple If Conditions

The below code contains two attributes to test if conditions.one attribute is the boolean type and another attribute is of type List.

<aura:component >
    <aura:attribute name="flag" type="Boolean"/>
    <aura:attribute name="arry" type="List" default="[1, 2, 3]"/>
    <div>
        <aura:if isTrue="{!v.flag}">
            <div class="slds-box">
                <span class="itIsTrue">It is true.</span>
            </div>
        </aura:if>
        <aura:if isTrue="{! !v.flag}">
            <div class="slds-box">
                <span class="itIsFalse">It is not true.</span>
            </div>
        </aura:if>
        <aura:if isTrue="false">
            <div class="slds-box">
                <span class="itIsLiterallyFalse">It is literally false.</span>
            </div>
        </aura:if>
        <aura:if isTrue="true">
            <div class="slds-box">
                <span class="itIsLiterallyNotFalse">It is literally not false.</span>
            </div>
        </aura:if>
    </div>
    <div>
        <aura:if isTrue="{!v.arry.length }">
            <div class="slds-box">
                Truthy
                <aura:set attribute="else">
                    Falsey
                </aura:set>
            </div>
        </aura:if>
    </div>
    
</aura:component>

Here is the simple App for testing. The first time when the component is instantiated we are setting the flag to false and array size is greater than zero.The second time we are getting the flag to true and array to empty.

<aura:application extends="force:slds">
    <div class="slds-box slds-theme--alt-inverse">
        <c:IFMaster flag ="false" arry="[1, 2, 3]"/>    
    </div>
    <div class="slds-box slds-theme--info">
        
        <c:IFMaster flag ="true" arry=""/>    
    </div>
</aura:application>

 Simple If Else

In this below code just I am using one flag to test if and else conditions. You can see an output with both the condition if the flag is true or false.

<aura:component >
    <aura:attribute name="flag" type="Boolean"/>
    
    <span aura:id="whatIsIt">
        <aura:if isTrue="{!v.flag}">
            <span>It is true.</span>
            <aura:set attribute="else">
                <span>It wishes it was true.</span>	
            </aura:set>
        </aura:if>
        <br/>
        <aura:if isTrue="{! !v.flag}">
            <span>It is not true.</span>
            <aura:set attribute="else">
                <span>It wishes it was not true.</span>	
            </aura:set>
        </aura:if>
    </span>
    
</aura:component>

Here is the simple App to invoke the component. When you set the flag as false it will display the false message as true condition and else message is coming from the else condition.

<aura:application extends="force:slds">
    <div class="slds-box slds-theme--alt-inverse">
        <c:IFMaster flag ="false" />    
    </div>
   
</aura:application>
When you set the flag as true
<aura:application extends="force:slds">
    <div class="slds-box slds-theme--alt-inverse">
        <c:IFMaster flag ="true" />    
    </div>
   
</aura:application>

 

Nested If Else

 The below code we have two attributes to show the outer and inner if conditions.
<aura:component >
    <aura:attribute name="outer" type="Boolean"/>
    <aura:attribute name="inner" type="Boolean"/>
    <span aura:id="whatIsIt">
        <aura:if isTrue="{!v.outer}">
            <span class="outerIsTrue">
                <span> Outer Is True. </span>
                <aura:if isTrue="{!v.inner}">
                    <span >Inner is true.</span>
                    <aura:set attribute="else">
                        <span >Inner is False .</span>   
                    </aura:set>
                </aura:if>
                <aura:if isTrue="{! !v.inner}">
                    <span >Inner  is not true.</span>
                    <aura:set attribute="else">
                        <span >Inner is true. </span>    
                    </aura:set>
                </aura:if>
            </span> 
            <aura:set attribute="else">
                <span >
                    Outer is Else .                   
                </span>         
            </aura:set>
        </aura:if>
    </span>   
</aura:component>
If you set both outer and inner attributes to the .it will display the data as shown below.
<c:IFMaster outer ="true" inner="false" />

If Else with Iteration 

The below code shows how to Iterate over the list and display the data based on the attribute “showEven”.

<aura:component >
    <aura:attribute name="arr" type="List"  default="[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]"/>
    <aura:attribute name="start" type="integer" default="4"/>
    <aura:attribute name="end" type="integer" default="14"/>
    <aura:attribute name="showEven" type="Boolean" default="true"/>
    
    <div class="container" aura:id="container">
        <aura:iteration aura:id="temo" items="{!v.arr}" var="number" indexVar="index" start="{!v.start}" end="{!v.end}">
            <div aura:id="simple" class="{!'row row'+index}">
                <aura:if isTrue="{!v.showEven}">
                    <aura:if isTrue="{! (mod(index,2)==0) ? 'true':'false'}">
                        index#{!index}:{!number}
                    </aura:if>
                    <aura:set attribute="else">
                        <aura:if isTrue="{! (mod(index,2)==1) ? 'true':'false'}">
                            index#{!index}:{!number}
                        </aura:if>   
                    </aura:set>
                </aura:if>
                
            </div>
        </aura:iteration>
    </div>
    
    
    
</aura:component>

If you set “showEven” to false it will display only odd numbers as shown below.

        <c:IFMaster showEven="false"/>    

If Else with Server Side Controller 

Simple Apex code that will return false

public class ServerSideCls {
    @AuraEnabled
    public static boolean showMessage(){
        return false ;
    }
    
}

Component

<aura:component  controller="ServerSideCls">
    
    <aura:attribute name="flag" type="Boolean"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <div class="container" aura:id="container">
        <aura:if isTrue="{!v.flag}">
            Server is Returning true 
            <aura:set attribute="else">
                Server is returning false .
            </aura:set>
        </aura:if>
    </div>
</aura:component>
({
    doInit: function(component, evt) {
        var action = component.get("c.showMessage");
        action.setCallback(this, function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                component.set("v.flag", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    },
    
})

When you invoke this component, it will display the message based value return from the server side code.