Showing posts with label Lightning. Show all posts
Showing posts with label Lightning. Show all posts

Thursday, October 13, 2022

lightning-tree-grid - Account Hierarchy Using lightning-tree-grid in LWC

 In this blog, I am going share a approach through which you can display account hierarchy using lightning tree grid. You can place this lightning component on account record page and it will detect the current account record Id and will display the complete hierarchy.

I am utilising formula field called "Ultimate Account id" to avoid multiple SOQL in apex to get list of all account in the hierarchy. This component can display all account which are up to 10 level deep in hierarchy.

Please refer below URL to get more idea about Ultimate Account Id formula field.

How to get list of all accounts present in account hierarchy in Salesforce

In this LWC component, I am just passing the account Id to apex method and apex method returns all the account list which are present in hierarchy. In order to display account in tree grid, I am creating data in js which will be accepted by tree grid. So in this approach, manipulation on apex side is very simple.


Note: Create Ultimate Account Id formula field on account first in order to implement below code.

Complete Code:

Hope this will help!!!




Monday, April 27, 2020

Javascript Promise.all : Way to perform action when Multiple Parallel enqueued Actions are Completed in Lightning Components

As we all know that all actions from Lightning components are sent to server in asynchronous manner and we can not predict the sequence about response from server.

If we have requirement to wait for all operations to complete and then perform some action on lightning components like hiding the spinner or displaying all data at once.

We can either queue the first server call and when we get response then we perform second server call. For this you can use Javascript Promise pattern to sequence the server call. Please refer below URL for complete understanding of sequencing of server call using javascript promise.

JavaScript Promises vs Callback Functions in Lightning Components

Now if we need to fire server calls in parallel and want to wait for all response, then you can utilize promise.all methods to achieve this. This will execute many promises in parallel and wait until all of them are ready. Below is syntax to use promise.all:
 
//create array of promise and pass it to promise.all 
var promiseArray =[promise1, promise2];
var combinedPromise = Promise.all(promiseArray);
//this return single promise. Now handle it with then and catch
combinedPromise
.then($A.getCallback(function(results){
 //handle success
 var promise1Results = results[0]; //Results from Promise 1
 var promise2Results = results[1]; //Results from Promise 2
})) 
.catch($A.getCallback(function () { 
 //Handle errors on any promise here
 console.log('Some error has occured'); 
}));

Note:
  • Promise.all takes an array of promises and returns a new promise.
  • The new promise resolves when all listed promises are settled, and the array of their results becomes its result.
  • Order of the resulting array members is the same as in its source promises. Even though the first promise takes the longest time to resolve, it’s still first in the array of results.
  • If any of the promises is rejected, the promise returned by Promise.all immediately rejects with that error.
  • For example, if there are multiple fetch calls and one fails, the others will still continue to execute, but Promise.all won’t watch them anymore. They will probably settle, but their results will be ignored. Promise.all does nothing to cancel them, as there’s no concept of “cancellation” in promises.
  • This will help to improve the performance of lightning components as server operations are not performed in sequential order. Due to parallel call to server, lightning components will perform better.
I have created a sample lightning component which fetch Account and Task records from server and displays it in UI only when both operations are completed and response is returned to lightning components. below is gif image displaying the lightning component functionality:


Below is complete snippet for your reference:

Hope this will help!!

Saturday, April 11, 2020

JavaScript Promises vs Callback Functions in Lightning Components

As we all know that all server calls from lightning components are asynchronous in nature. If we call 2 different apex methods from lightning components, then there is no surety that which will return response first. In order to provide sequencing between these 2 calls, we have to write second method call in callback function of first apex call as mentioned below:

findDataUsingNormalCall : function(component, event, helper) {
  var actionName1= component.get("c.findMyAccounts");
  var params1={"numberOfRecords":2};
  actionName1.setParams(params1);
  actionName1.setCallback(this, function(response) {
    var state = response.getState();
    if (state === "SUCCESS") {
        var apexResponse1=response.getReturnValue();
        component.set("v.ltngAccList",apexResponse1);
       //Now perform second Call
        var actionName2= component.get("c.findMyPendingTasks");
        var params2={"numberOfRecords":2};
        actionName2.setParams(params2);
        actionName2.setCallback(this, function(response) {
           state = response.getState();
           if (state === "SUCCESS") {
              var apexResponse2=response.getReturnValue();
              component.set("v.ltngTaskList",apexResponse2);
           }else if(state === "ERROR"){
              var errors2 = response.getError();
              console.error(errors2);
           }
        });
        $A.enqueueAction(actionName2);
     }else if(state === "ERROR"){
        var errors1 = response.getError();
        console.error(errors1);
     }
  });
  $A.enqueueAction(actionName1);

Now if you have to perform multiple server side apex calls from lightning components in sequential order, code becomes very difficult to understand and read and difficult to maintain this kind of code.

Javascript Promises

Promise pattern is very common in javascript to handle asynchronous operations.  Prior to promises events and callback functions were used but they had limited functionalities and created unmanageable code.

Promise can have 3 states:
  • Pending
  • Fulfilled
  • Rejected
Use below syntax to create promise:

var promise1 = new Promise($A.getCallback(function(resolve, reject){
     //perform logic like server call
     if (/* success */) {  
        resolve("result");
     }else {
        reject("error");
     }
}));
  • Constructor takes only one argument as a function. 
  • Callback function takes two arguments, resolve and reject
  • Perform operations inside the callback function and if everything went well then call resolve.
  • If desired operations do not go well then call reject.
In order to consume promise, use .then or .catch methods as shown below:

promise1 . 
    .then($A.getCallback(function(result){
             //handle success
 }), 
 $A.getCallback(function(error){
            //handle error
        })
     ) 
    .catch($A.getCallback(function () { 
        console.log('Some error has occured'); 
    }));

Remember:
  1. then() method automatically invoked when promise is either resolved (fulfilled) or reject.
  2. then() method takes 2 functions as parameters:
    • If promise is resolved and a result is received, First function is executed.
    • If promise is rejected and an error is received, Second function is executed(optional).
  3. catch() method is invoked when a promise is either rejected or some error has occurred in execution. catch take 1 function as parameter. If you are using the second parameters for then function then use catch for error handling.
Calling multiple asynchronous functions and Chaining them using Promises

You can use below pattern in order to perform different asynchronous operation in synchronous manner.

new Promise($A.getCallback(function(resolve, reject){}))
    .then(
        // resolve handler
        $A.getCallback(function(result) {
   //when first call is successfull, then create new 
   //instance of promise to make another call
          return new Promise($A.getCallback(function(resolve,reject){}));
        }),
 // reject handler
        $A.getCallback(function(error) {
            console.log("Promise was rejected: ", error);
    //you can create another promise for error handling
        })
    )
    .then(
        // resolve handler
        $A.getCallback(function() {
            //perform logic when second call is successfull
        })
    );
I have created a sample lightning component which explain the functionality of callback function and promise pattern. Below are details about this component functionality:
  • Component contains 2 button which invoke 2 different apex methods by using callback pattern and promise pattern.
  • When user clicks on "Fetch 2 records using callback pattern" button, system fires 2 server calls to get account and task records in asynchronous manner. So records will get displayed on UI based on response from server. There will be no sequencing of these 2 method invocation.
  • When user clicks on "Fetch 3 records using promise pattern", system first fire an asynchronous call to get account records and once account data is recieved, then it will fire another asynchronous call to get task records. This functionality uses promise pattern to fire 2 asynchronous call in synchronous manner. 


Below is code snippet:

Best Practices:
  • Always use catch or reject handler.
  • Always use $A.getCallback() when using promise pattern in lightning components. Even if you do not use this, then sometimes it will work but it will be very difficult to debug if something went wrong. Sometimes if you don't use it, then results may get delayed on UI and can cause performance issues. 
Hope this will help!!

Tuesday, November 19, 2019

How to Convert Salesforce Classic Notes into Lightning Notes

As now everyone is migrating to Lightning, Salesforce supports lightning Notes(ContentNote) instead of Classic Notes. So while migrating to lightning, we have to convert all classic Notes to lightning Notes. Salesforce provide an appexchange app called magic mover for this purpose.

If you don't want to install this app and would like to perform this conversion, then you can do it with very simple apex script.

If you want to understand How to Convert Salesforce Attachments into Salesforce Files then refer below URL:

Convert Salesforce Attachments into Salesforce Files


I have created a batch class which will convert all Notes related to object (based on query that you pass) to ContentNote and you will receive an email with all details once batch job is completed.

Suppose you want to convert all the notes related to Account to Lightning Notes, then use below script in execute anonymous in developer console.

string qstring='Select id from Account';
SK_ConvertNotesForLightningBatch newjob= new SK_ConvertNotesForLightningBatch(qstring);
database.executeBatch(newjob);

Below is snapshot of csv file which you receive after this batch job completed.

Hope this will help!!

Thursday, November 14, 2019

Pre-populate Field Values on Standard Pages in Lightning

In Salesforce classic, we used to specify the field values in URL parameters (URL hacks) to pre-populate the field values in standard page layouts.

In lightning, URL hack don't work. So if we have to open standard page in lightning with pre-populated field values, then we can use "e.force:createRecord" event to open new record page with default field values.

In this blog, I will be creating a lightning component which will be added to account page layout. This component will display button "Create Quick Contact" to create new contact. When user will click on this button, standard new contact page will open with default field values.

Below is complete code:

Now you add this component on account page layout.

Now when you click on Create Quick Contact, standard page will open for new contact creation with pre-filled field values specified in controller.js.


Here you can see recordtypeId, phone, email and account are pre-populated.

Hope this will help!!




Thursday, November 7, 2019

How to Convert Salesforce Attachments into Salesforce Files

As now everyone is migrating to Lightning, Salesforce supports files instead of attachment. So while migrating to lightning, we have to convert all attachments to files. Salesforce provide an appexchange app called magic mover for this purpose.

If you don't want to install this app and would like to convert attachments to files, then you can do it with very simple apex script.

I have created a batch class which will convert all attachments related to object (based on query that you pass) to files and you will receive an email with all details once batch job is completed.

Suppose you have to convert all attachments of Contact to files, then use below script:
SK_ConvertAttachmentsToFilesBatch newjob= new SK_ConvertAttachmentsToFilesBatch('select id from Contact');
database.executeBatch(newjob, 1);




I will suggest to run this batch job with minimum batch size (recommended size is 1). Suppose if you run this script with more batch size and one parent record have multiple attachments and attachment size is large, then you may face heap size error in apex script. So it is advisable to run this script with batch size as 1.

Hope this will help!!

Sunday, May 19, 2019

Lightning:NotificationsLibrary : Easy Way to Display Toast or Notices in Lightning

In order to display the toast messages, we have to fire standard event "force:showToast". Now Salesforce recommend using lightning:notificationsLibrary for displaying messages in lightning via notices and toasts.

Toast helps in providing information about status on user action.
Notices helps in displaying the system related issue or update about any maintenance.

NotificationsLibrary makes very easy for developer to display notices and toast.

How to display Notices using lightning:notificationsLibrary

Below is sample code:


How to display Toast using lightning:notificationsLibrary

Below is sample code:

Hope this will help!!!

Thursday, May 16, 2019

Handling Platform Events in Lightning Components

The lightning:empApi component gives methods for subscribing to a streaming channel and listening to event messages. It supports all streaming channels including channels for platform events, pushTopic events and Change Data Capture events. The lightning:empApi component uses a shared CometD connection.

Note:
  • This component is available in 44.0 api version or later.
  • This is available in Lightning Experience and only supported in desktop browsers.
To call the component's methods, add the lightning:empApi component inside your custom component and assign an aura:id attribute to it.

If you want to learn more about platform events then refer below blog:

Platform Events : Way to Deliver Custom Notifications within Salesforce or to external Applications

I have created a lightning component which will subscribe to platform event "Demo_Event__e" which we have created in our previous blog.

I have created an app page using lightning app builder named as "Platform Events App Page". and added this lightning component into it.

Code Snippet:

Below is snapshot of Lightning App page before platform event is fired.

Now fire platform event using workbench through REST API call

Platform event notification received in lightning component.

Hope this will help to understand platform events handling in lightning components. 

Looking forward for everyone's suggestions and comments!!!


Saturday, February 16, 2019

How to get User Locale information in Lightning Components

Lightning framework provide $Locale which can be used to get current user preferred locale. For example you can get user preferred timezone, language, currency format etc.

In Spring'19, Salesforce introduces new date-time $Locale attributes for date- time formattingas mentioned below:
  • longDateFormat ("MMMM d, yyyy")                              
  • shortDateFormat ("M/d/yyyy")
  • shortDatetimeFormat ("M/d/yyyy h:mm a")
  • shortTimeFormat ("h:mm a")
You can refer this global variable either directly in lightning component markup or in controller.js  file.

Below is sample code:

Snapshot of lightning component

For detailed information on Locale global variable, please refer below URL:
$Locale in Lightning Component


Hope this will help!!!

Friday, January 18, 2019

Lightning:map - Way to display location on map either by using address or geo-location

Salesforce introduces new tag in lightning framework "lightning:map" which can be used to securely displays map of one location or many locations.

You can either use address (make sure postalcode,country are specified) or geolocation (latitude and longitude).

Below is syntax to use lightning:map

<lightning:map
    mapMarkers="{!v.mapMarkers}">
</lightning:map>

where mapMarkers is an array of marker to display location. Below is JSON sample for markers:

[{
"location": {
"Country": "USA",
"State": "CA"
},
"icon": "standard:account",
"title": "Western Telecommunications Corp.",
"description": "CA,USA"
},
{
"location": {
"City": "Lawrence",
"Country": "USA",
"PostalCode": "66045",
"State": "KS"
},
"icon": "standard:account",
"title": "Dickenson plc",
"description": "Lawrence,KS,66045,USA"
}]

If you know geo-location of address then, you can pass latitude and longitude in location as shown below:

[{
    location: {
'Latitude': '37.790197',
'Longitude': '-122.396879'
},
    title: 'Western Telecommunications Corp',
    description: 'Western Telecommunications Corp',
    icon: 'standard:account'
}]


I have created a sample lightning component which fetch account billing address and display it on google maps using Lightning:map tag.


Complete Code:


Note:
  • If you specify address, then you must specify City, PostalCode, State or Country.
  • If you specify both address and geo-location, then map will be plotted using latitude and longitude.
  • If any mapMarker is invalid, then nothing will be plotted on map even other map markers.

Hope this will help!!!

Monday, December 24, 2018

How to set or get picklist (drop down) values in Lightning Components

Through this blog, I am going explain different syntax which can be used to create drop down (picklist) in lightning along with setting their their default values and fetching the user selected values in controller.js functions.

So will start with basics, if we already know different picklist or dropdown values then we can directly specify then in lightning markup as shown in below syntax:

Static Picklist

<lightning:select name="cStat" label="Case Status" value="New" aura:id="statusPicklist" >
<option value="">choose one...</option>
<option value="New">New</option>
<option value="In Progress">In-Progress</option>
<option value="Resolved">Resolved</option>
<option value="Closed">Closed</option>
</lightning:select>


"value" attribute  in lightning:select helps in pre-populating the default picklist value.

If you need to fetch the selected picklist value in controller.js, then use below syntax:

var selectedPicklistValue= component.find(“statusPicklist”).get(“v.value”);

Attribute Association with lightning:select

You can associate any attribute with lightning select and use that in "value" attribute of lightning select as shown below:

<aura:attribute name="ltngSelectedvalue" type="string" default="New"/>
<lightning:select name="cStat" label="Case Status" 
value="{!v.ltngSelectedvalue}" aura:id="statusPicklist" >
<option value="">choose one...</option>
<option value="New">New</option>
<option value="In Progress">In-Progress</option>
<option value="Resolved">Resolved</option>
<option value="Closed">Closed</option>
</lightning:select>

So in controller, you can directly get the value of attribute associated with lightning:select in order to get selected value for picklist.

var selectedPicklistValue= = component.get(“v. ltngSelectedvalue”);

Dynamic Picklist

When you are not sure of picklist options, then you can use dynamic picklist option. Different scenarios includes like passing picklist options from apex controller or using describe to get values for custom fields (picklist) created in salesforce.

Scenario 1

If the picklist label (displayed on UI) and values are similar then you can create an attribute of type "List" and use "aura:iteration" to create picklist options dynamically on UI. Below is sample syntax:

<aura:attribute name="options" type="List" 
default="['New','In Progress','Resolved','Closed']"/>
<aura:attribute name="ltngSelectedvalue" type="string" default="New"/>
<lightning:select name="cStat" label="Case Status" 
value="{!v.ltngSelectedvalue}" aura:id="statusPicklist" >
    <aura:iteration items=”{!v.options}” var=”opt”>
<option value="{!opt}">{!opt}</option>
    </aura:iteration>
</lightning:select>

Scenario 2

If picklist label on UI and values corresponding to then are different, then you can create a wrapper in apex class which contains 2 variables and return list of wrapper as different picklist options to lightning component attribute.

Public class picklistWrapper{
Public string pickListLabel;
Public string pickListValue;
}

Below is sample apex class which can be used to get picklist values using wrapper variable

Now in lightning component, you can call this apex method to fetch case status values and set it in attribute of type "object".
<aura:attribute name="options" type="Object"/>
In controller, store response from apex in variable and set the aura attribute

var apexResponse=response.getReturnValue();
//set response to attribute value
component.set("v.options",apexResponse);

In order to learn how to call apex method from lightning component refer below URL:
Calling Apex Method from Lightning Component

Below is sample code:

<!-- set options attribute through controller.js function call-->
<aura:attribute name=”options” type=”Object”/>
<aura:attribute name="ltngSelectedvalue" type="string"/>
<lightning:select name="cStat" label="Case Status" 
value="{!v.ltngSelectedvalue}" aura:id="statusPicklist" >
    <aura:iteration items=”{!v.options}” var=”opt”>
<option value="{!opt.pickListValue}">{!opt.pickListLabel}</option>
    </aura:iteration>
</lightning:select>

How to get selected picklist value on change event

You can also use onchange event on lightning:select to store the selected value by user in some aura:attribute.

<aura:attribute name=”options” type=”Object”/>
<lightning:select name="cStat" label="Case Status" aura:id="statusPicklist" 
onchange="{!c.onChange}">
<aura:iteration items="{!v.options}" var="opt">
<option value="{!opt.pickListValue}">{!opt.pickListLabel}</option>
</aura:iteration>
</lightning:select>

In controller.js, use below function:

onChange: function (cmp, event, helper) {
var selPickListValue = event.getSource().get("v.value");
        console.log('******selPickListValue :'+selPickListValue );
}

Note:

  • Event handler helps in identifying which markup element have been changed.
  • You can use event to get user selected element. Suppose user change the dropdown, value then by using event methods you can identify which dropdown value was changed by user along with its value.
  • You can get any attribute value of component through which user interacted on UI. for example event.getSource().get("v.name") will return "cStat" which is name attribute in lightning select.

Hope this will help!!!

Thursday, November 15, 2018

Lightning Treegrid : Generic Component to display hierarchy in tabular format for any sobject

In this blog, I am going to share a reusable component which can be used to display hierarchy of records along with other fields information in treegrid format.

Previously we have to use jquery to implement this but now "Lightning:treegrid" tag have been introduced which can be used to display treegrid in lightning framework.

In order to use this component, you have to pass below parameters to this components:
  • ltngcurrentRecId =  RecordId (15 or 18 digit)
  • ltngSobjectName = Object API Name
  • ltngParentFieldAPIName = Parent Field API name which create self relationship
  • ltngColumnLabelList = Specify the column label
  • ltngColumnAPINameList = Specify the API field names in same order as that of column
  • ltngHyperlinkColumn = Field API Name which will work as hyperlink for record detail page
Suppose you have display treegrid for Account hierarchy by using below syntax:

<c:SK_GenericTreeGridCmp ltngcurrentRecId="0019000000ld4kS"
ltngSobjectName="Account"
ltngParentFieldAPIName="ParentId"
ltngColumnLabelList="['Name','Type','Industry','Account Owner']"
ltngColumnAPINameList="['Name','Type','Industry','Owner.Name']"
ltngHyperlinkColumn="Name"/>

Below is output:

Suppose you have to display case hierarchy, then use below code snippet:

<c:SK_GenericTreeGridCmp ltngcurrentRecId="5009000000GJkJE"
ltngSobjectName="Case"
ltngParentFieldAPIName="ParentId"
ltngColumnLabelList="['CaseNumber','Subject','Status','Case Owner']"
ltngColumnAPINameList="['CaseNumber','Subject','Status','Owner.Name']"
ltngHyperlinkColumn="CaseNumber"
ltngHeaderValue="Case Hierarchy"/>

Below is output snapshot


Below is complete code snippet for your reference:


You can download the code from GitHub by using below URL:
Lightning-Treegrid-Generic-Component-to-display-hierarchy-in-tabular-format-for-any-sobject

Note:

  • Specify Field API properly as javascript is case sensitive. For example, specify "Name" instead of "name"
  • For adding parent field API names, provide API names properly. For example for Account owner use, "Owner.Name" instead of "owner.name".
Hope this will help!!!

Saturday, November 10, 2018

Lightning Components Tutorial : Easy way to become Lightning developer

In this blog, I am going to share all lightning components concept which is required for Lightning developer starting from basics to advance topics.

You can learn lightning by following below blogs related to lightning.
  1. Lightning Component Basics: Lightning Component Framework
  2. Lightning Components Basics : Attributes, Expressions and Value Providers
  3. Lightning Components Basics : Handling Actions in Controller.js
  4. How to set or get picklist (drop down) values in Lightning Components
  5. Lightning Components Basics : Considerations while calling server-side controller actions
  6. Application Events : Way to Communicate Between Different Lightning Components
  7. Component Events: Way to Communicate Between Components in Containment Hierarchy
  8. Raising and Handling Custom Events in Salesforce Lightning
  9. Salesforce Lightning Events : Hands on Training Guide
  10. Salesforce 1 Events in Lightning Experience and Salesforce 1 app
  11. Lightning Data Services : Way to perform operation on records without using server-side Apex class
  12. Lightning Data Services : Hands on Training Guide
  13. Creating Lightning Components Dynamically
  14. Dynamically Creating and Destroying Lightning Button(ui:button)
  15. Adding Lightning Components in VF Page and Passing Values from URL
  16. Inheritance in Lightning Components
  17. Firing Event from Lightning Component and Passing Parameter to VF Page
  18. How to Fire Lightning Events from VF Page in Lightning
  19. Custom Component to show Loading Spinner in Lightning during Server or Client side Operations
  20. Why to use design resource in Lightning bundle and how to add dynamic Options in datasource for Design Component
  21. Formatting and Localizing dates in javascript in Lightning
  22. Using Chartjs in Lightning Components
  23. Lightning Tree : Generic Lightning Component to Display Hierarchy for any sObject
  24. Lightning:treegrid - Displaying Account hierarchy using treegrid
  25. Aura.Action : Lightning Framework Specific Attributes Type
  26. Aura.Component[] : Lightning Framework Specific Attributes Type

Hope this will help!!

Tuesday, November 6, 2018

Aura.Action : Lightning Framework Specific Attributes Type

In this blog, I am going to explain "Aura.Action" attribute type and its usage.

There is another Lightning Framework specific attribute "Aura.Component[]". If you want to learn more about this then refer below blog:

Aura.Component[] : Lightning Framework Specific Attributes Type


Aura.Action

Use this type of attribute if you want to pass the reference of parent lightning component controller.js function to nested/child lightning component. This will help to invoke parent component JS function from child component markup.

Below is syntax to define this kind of attribute:

<aura:attribute name="parentJSFunction" type="Aura.Action"/>

This is useful if you want to make reusable component to appear based on values passed from parent and close/hide the component by invoking parent lightning component JS function.

I have created a sample component to explain how to invoke parent component function and child component function by passing "Aura.Action" attribute to child component.

Below is snapshot of Lightning component ("SK_AuraActionDemoCmp")  UI which contains child component ("SK_AuraActionChildCmp")  inside it.


Child component contains 2 buttons which will invoke JS function of parent and same component. Child component contains an attribute of type "Aura.Action" through which we will parent parent component JS function reference.

<aura:attribute name="closeChildDivFunction" type="Aura.Action" default="{!c.defaultCloseAction}"/>

If you don't pass JS function from parent component then child component will invoke its own JS function "defaultCloseAction".

If user click on these 2 buttons, then below things will happen:

  • If user clicks on "Close via Parent JS function" button,then complete content will also get removed and ltnguserActionMessage will display message saying "Close via Parent JS function button clicked. Please refresh your browser if you again want to load this demo component"

  • If user clicks on "Close via ChildCmp JS function" button,then only child component body will be removed and ltnguserActionMessage  will display message saying "Close via ChildCmp JS function button clicked.Please refresh your browser if you again want to load this demo component"



Please find below complete code reference:

Hope this will help!!


Thursday, November 1, 2018

Lightning:treegrid - Displaying Account hierarchy using treegrid

Salesforce has introduced new tag called lightning:treegrid which can be used to display tree structure in tabular form. Lightning:tree can be used to display the hierarchy but if you want to display additional information then lightning:treegrid becomes useful.

If you want to lean how to use lightning:tree tag to display hierarchy for any record then refer below URL:

Lightning Tree : Generic Lightning Component to Display Hierarchy for any sObject

If you have to display account hierarchy along with another fields information as displayed in below image, then use treegrid.


Below is complete code to display account hierarchy. Just pass account record Id and lightning component will display complete hierarchy.


Hope this help!!!

Tuesday, October 30, 2018

Aura.Component[] : Lightning Framework Specific Attributes Type

We know that there are different attribute types supported for attribute in lightning like Boolean, date, datetime, decimal, double, integer, long, string, collections (list,set,map), sobjects, user defined data types(wrapper class) etc.

Below are 2 different types which are supported as attribute type and specific to lightning framework:
  • Aura.Component[]
  • Aura.Action
In this blog, we are going cover all aspect of Aura.Component[] attribute type. If you are interested in learning more about Aura.Action, then refer below blog:

Aura.Action : Lightning Framework Specific Attributes Type

Aura.Component[]

An attribute of this type is considered as facet. You can use this in order to set markup to use it in multiple places.
You can consider it some what similar to defining templates with <apex:composition> in VF pages.

To set a default value for "Aura.Component[]", specify the default markup in the body of aura:attribute. For example:

<!--aurafacet.cmp-->
<aura:component>
<aura:attribute name="MarkupDetail" type="Aura.Component[]">
<p>Aura.Component[] default value</p>
</aura:attribute>
</aura:component>

So when this facet attribute(MarkupDetail) value is not set in component, then this default mark up will apear.

<aura:component>
    <c:aurafacet >        
        <!--we are not setting MarkupDetail attribute value so this will display 
default body specified in MarkupDetail attribute--> 
    </c:aurafacet>
</aura:component>

Output will be:

Aura.Component[] default value

Below is sample code which include different components and usage of Aura.Component[] in it. Also it will explain how to reuse the component body.

Below is output snapshot:

Points to be noted:

  • When we didn't set the attribute value of type Aura.Component[], then it display default body specified within Aura.Component[].
  • When we set attribute value of type Aura.Component[], component will render based on given values.
  • Different div are being getting created with different content in that.

Hope this helps!!!

Thursday, October 4, 2018

Lightning Component Basics: Lightning Component Framework

In this blog, I am going to provide basic overview of lightning component framework.

Lightning component framework is being referred as MVCC modal.

  • Modal
  • View
  • Client-Side Controller
  • Server-Side Controller
In lightning components, Lightning bundle which contains component markup, controller.js (client-side), helper.js (for utility or reusable code) etc acts as primary interface and from client side controller, we can perform server side calls(apex class method invocations).

All calls from Lightning components to server are asynchronous call and we capture the response using callback function.

Below diagram will help you to understand Lightning component framework:


Hope this will help!!!

More Blogs:



Saturday, September 29, 2018

Lightning Components Basics : Considerations while calling server-side controller actions

In this blog, we will cover how to call apex class method from Lightning component and different considerations that we need to consider while performing server side call. Actually all calls to server for apex class routed through controller.js function. From lightning component, you can call controller.js function from where you can call apex method.

First of all in order to associate an apex class with lightning component, you have to specify apex class name in controller attribute.

Also remember that all apex methods or apex member variables needs to annotated with @AuraEnabled.

Below is sample apex class which will be called from lightning:

public class SK_LightningBasicsSSController {
    @AuraEnabled
    public static List<Account> findRecentAccounts(){
        return [select id,name,type from Account 
                order by LastmodifiedDate DESC Limit 10];
    }
}

In order to associated this class with lightning component, use below syntax:

<aura:component controller="SK_LightningBasicsSSController">
    <!-- you code-->
</aura:component>

Now we will call apex method on load of lightning component and will display returned list of accounts.

Below is process to call apex method from controller.js

//Create instance of apex method by using c. annotation followed by method name.
var actionName= component.get("c.findRecentAccounts");
//Specify the callback function as all calls are asynchronous. this callback will be invoked once //response is returned by apex class
actionName.setCallback(this, function(response) {
var state = response.getState();
 //Check response state for SUCCESS and ERROR
if (state === "SUCCESS") {
  //store the response in variable
var apexResponse=response.getReturnValue();
console.log('***'+JSON.stringify(apexResponse));
                //set response to attribute value
component.set("v.ltngAccountList",apexResponse);
}else if(state === "ERROR"){
var errors = response.getError();
console.error(errors);
alert('Problem with connection. Contact your system administrator.');
}
});
//do not forget to add below line as this put this request in queue for asynchronous call
$A.enqueueAction(actionName);

Below is complete code snippet:



Important Points to remember:

How to call apex method which contains parameters


If you have method defined with some parameter, for example search string to search account as mentioned below:

@AuraEnabled
Public static List<Account> SearchAccounts(string searchString){
       //your logic
}

So in order to pass parameters to apex class method, create a JSON as mentioned below:
Suppose you have an attribute defined to take input from user say AccName:

<aura:attribute name="AccName" type="string"/>

var actionName= component.get("c.SearchAccounts");
var params = {
                         "searchString" :component.get("v.AccName")
                      };
actionName.setParams(params);

Note:
  • While creating JSON for parameters, key Value should be similar to parameter name in apex method. In our case the apex method parameter name was "searchString" so while creating JSON we specified first key Value as "searchString".
  • If you have multiple parameters, then create JSON as mention below:
          var params ={
                                 "param1":"param value1",
                                 "param2": "param value2",
                                 "param3": "param value3"
                               };

Create helper function which can be reused for different apex method calls

Instead of writing same piece of code to call different apex methods, we can write function in helper.js which can be invoked from controller.js function by passing the parameters to it.

I have created a helper function which takes 4 parameters:
  • Component reference
  • apex class method name
  • callback function name
  • param (to specify parameters if apex method expect some parameters or arguments)
Below is helper function "callToServer"

({
callToServer : function(component, method, callback, params) {
        var action = component.get(method);
        if(params){
            action.setParams(params);
        }
        console.log('****param to controller:'+JSON.stringify(params));
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                callback.call(this,response.getReturnValue());
            }else if(state === "ERROR"){
                var errors = response.getError();
                console.error(errors);
                alert('Problem with connection.'+errors);
            }
        });
        $A.enqueueAction(action);
    }
})

Now if you have to call apex class method from controller.js then use below syntax:

({
    doInit : function(component, event, helper) {
        var params = {
                                 "searchString" :component.get("v.AccName")
                              };
        helper.callToServer(
            component,
            "c.SearchAccounts",
            function(response)
            {
                console.log('apex response :'+JSON.stringify(response));
                component.set("v.ltngAccountList",response);
            }, 
            params
        );
    }
})

How to call different apex methods in sequential order

All calls to apex methods are asynchronous so if there is need to first call a apex method and based on response call another apex method, then you need to make sure that you perform second call to server after getting the response from first function.
So always perform second call to server from inside the callback function which get invoked when asynchronous call finished on server. 

If you use helper function approach to call apex methods then you can use below syntax to call 2 different (searchAccounts and findAccountdetailsapex method in sequential order.

var param1= {
                         "searchString" :component.get("v.AccName")
                     };
helper.callToServer(
component,
"c.SearchAccounts",
function(response)
{
component.set("v.ltngAccountList",response);
var selectedId = response[0].id;
var param2 = {
"ltngAccId": selectedId
}
//creating component dynamically using helper function
helper.callToServer(
component,
"c.findAccountdetails",
function(response)
{
   //your logic
},
param2
);
}, 
param1
);

Use Wrapper to get all data in single call

Avoid multiple calls to server in order to fetch information as it will degrade the performance.
Use wrapper (user defined data types) to return complete information in single server call.


Hope this will help!!!


Friday, September 28, 2018

Lightning Components Basics : Handling Actions in Controller.js

Lightning component bundle comes with different resources like controller.js, helper.js, style.css etc.

All the actions performed on lightning component, can be handled in controller.js.
helper.js worked as an utility which can be called multiple times. If you want to call same piece of code multiple times, then specify it as separate reusable function in helper.js and call it from controller.

I have created a sample lightning component "SK_LightningBasics". Below is code for that:

SK_LightningBasics.cmp

<aura:component >
    <aura:attribute name="ltngFirstname" type="string" default="Sunil"/>
    <aura:attribute name="ltngLastname" type="string" default="Kumar"/>
    <!--Mark up starts-->
    <lightning:input aura:id="userFn" value="{!v.ltngFirstname}" name="ufn" label="Firstname"/>
    <lightning:input aura:id="userLn" value="{!v.ltngLastname}" name="uiln" label="Lastname"/>
    <lightning:input aura:id="useremail" value="" name="uinput" label="Enter Email"/>
    <lightning:button name="btn" label="Display" onclick="{!c.displayMessage}"/>
    <!--Mark up ends-->
</aura:component>

SK_LightningBasicsController.js

({
displayMessage : function(component, event, helper) {
             var fname= component.get("v.ltngFirstname");
             var lname= component.get("v.ltngLastname");
             //how to get input by user 
             //which is not related to attribute
             var emailInputTag= component.find("useremail");
             //Now you can refer any attribute on input tag
            var emailvalue= emailInputTag.get("v.value");
            console.log('*******emailvalue-'+emailvalue);
            //to find label for email input
            var emailLabel= emailInputTag.get("v.label");
            console.log('*******emailLabel-'+emailLabel);
            var alertMsg='displayMessage function get called.\n';
           alertMsg = alertMsg +'Email entered is -'+emailvalue;
           alert(alertMsg);
    }
})

Lightning is based on MVCC (Modal-View-Client side controller-Server side controller), so first functions defined in controller.js is called first and then if needed we can call server side apex class methods.

In above lightning components, we are using onclick attribute on lightning button which invokes controller.js function.

In lightning, we refer controller.js functions using c.annotation inside "{! and }".
For example{!c.displayMessage}

Way to invoke controller.js function when component loaded initially

Lightning framework provide standard events which can be used to invoke controller.js function.
Use below syntax to invoke controller.js function when component is getting loaded:

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

Specify the controller.js function which you want to invoke. By using above code snippet, we are calling doInit function in controller.js.

({
doInit: function(component, event, helper) {
             alert(' doInit get called');
      },
      displayMessage : function(component, event, helper) {
             //your logic
      } 
})

Way to invoke controller.js function when any attribute value gets changed

Use change event on attribute to invoke controller.js function.

Sample code snippet:

<aura:attribute name="ltngFn" type="string" default="Sunil"/>
<aura:handler name="change" value="{!v.ltngFn}" action="{!c.OnChangeFunction}"/>

So whenever "ltngFn" attribute value will be changed then, OnChangeFunction will be invoked

({
doInit: function(component, event, helper) {
             alert(' doInit get called');
      },
      displayMessage : function(component, event, helper) {
             //your logic
      },
      OnChangeFunction: function(component, event, helper) {
             alert(' Attribute value gets changed');
      } 
})

In order to test these component code, you can either create lightning tab or create lightning app and preview it. Below is code for lightning app:

SK_LightningBasicsApp.app

<aura:application extends="force:slds">
    <c:SK_LightningBasics/>

</aura:application>

After creating this app, click on preview button on top right side in developer console.

Hope this will help!!


Saturday, September 22, 2018

Lightning Components Basics : Attributes, Expressions and Value Providers

Attributes
Attributes are just like apex class member variables which holds some value and can be used in performing any operation.
Same like apex class member variable, you need to define name of attribute, datatype of attribute and you can also define default value which is optional.
Below is syntax to define attribute:

        <aura:attribute name="firstname" type="string" default="Sunil"/>

Other attributes are:
  • access- Indicates whether the attribute can be used outside of its own namespace. Possible values are public (default), and global, and private.
  • required - If it is required to specify the value of attribute. The default is false.
  • description - Specify the purpose and usuage of attribute.
Supported values for type are Boolean, date, datetime, decimal, double, integer, long, string, collections (list,set,map), standard and custom objects and user defined data types(wrapper class).

Please refer below URL for more information on basic data types:

Component Attributes Types
                                   
Note:
Salesforce recommend using type="Map" instead of type="Object" to avoid some deserialization issues on the server. For example, when an attribute of type="Object" is serialized to the server, everything is converted to a string. Deep expressions, such as v.data.property can throw an exception when they are evaluated as a string on the server. Using type="Map" avoids
these exceptions for deep expressions, and other deserialization issues.

Checking for Types
To determine a variable type, use "typeof" or a standard JavaScript method instead. The "instanceof" operator is unreliable due to the potential presence of multiple windows or frames.

Expression

Expression are kind of formula which can be used within expression delimiters (“{!” and “}”)in expressions, you can specify attributes or different operators to give you output.

          <aura:attribute name="msg" type="String"/>  
            <p>{!'Hello! ' + v.msg}</p>

Value Providers

Value providers helps you to access attributes values and you can use them either in component markup or in JavaScript functions. Using value providers, you can either set or get attributes values.

        <aura:attribute name="msg" type="String"/>  
            <p>{!'Hello! ' + v.msg}</p>

  • Way to find attribute value in controller.js:

               var msgValue = component.get("v.msg")

  • How to set attribute value in controller.js

              component.set("v.msg","Sunil Kumar");