Friday, November 27, 2020

Fan Switch Example | Understanding Communication between Lightning components

In this article we are going to see a simple FAN switch on/off example. Concept used here are:

1) Parent to child communication using Aura Method

2) Using Static Resource in lightning component 





ChildFan.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global"> <aura:method name="imageMethod" action="{!c.doAction}" > <aura:attribute name="imageinfo" type="Boolean" default="false"/> </aura:method> <aura:attribute name="fantype" type="Boolean" default="false"/> <div class="slds-align_absolute-center"> <aura:if isTrue="{!v.fantype}"> <img style="border: 8px solid black;" src="{!$Resource.FanOn}"/> <aura:set attribute="else"> <img src="{!$Resource.FanOff}"/> </aura:set> </aura:if> </div> </aura:component>


ChildFan.js

({ doAction : function(component, event, helper) { var params = event.getParam('arguments'); if (params) { var param1 = params.imageinfo; component.set("v.fantype",param1); } } })


ParentFan.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" > <div class="slds-align_absolute-center"> <button class="buttonclass1" onclick="{!c.FanOn}">ON</button> <c:childFan aura:id="childFan"></c:childFan> <button class="buttonclass2" onclick="{!c.FanOff}">OFF</button> </div> </aura:component>



ParentFan.js

({ FanOn : function(component, event, helper) { var childFanComp = component.find('childFan'); childFanComp.imageMethod("true"); }, FanOff : function(component, event, helper) { var childFanComp = component.find('childFan'); childFanComp.imageMethod("false"); } })

Thank you..!!

Sunday, October 11, 2020

Transaction Control Using Database.setSavepoint and Database.rollback

In this article we are going to understand and implement transaction control using Database class methods setSavePoint and rollback which help to restore and rollback the partial work i.e already executed DML statements in a apex transaction. 


Sometimes during the processing of records, your business rules require that partial work (already executed DML statements) be “rolled back” so that the processing can continue in another direction. Apex gives you the ability to generate a savepoint that is, a point in the request that specifies the state of the database at that time. Any DML statement that occurs after the savepoint can be discarded, and the database can be restored to the same condition it was in at the time you generated the savepoint.

Database.setSavepoint() is used to define a point at which DML operations can be rolled back. If any error occurs during DML Operations, that contains many statements, the application will be rolled back to the most recent save point and the entire transaction will not be aborted.

Let's see an example below to understand this:

Account acc = new Account(Name = 'Salesforce Learning Hub'); insert acc;

//Since we didn't provided the AccountNumber, it will be null

System.assertEquals(null, [SELECT AccountNumber FROM Account WHERE Id = :acc.Id]. AccountNumber); // Create a savepoint while AccountNumber is null Savepoint sp = Database.setSavepoint(); // Saveponit created here

// Change the account number acc.AccountNumber = '123'; update acc;

//Now account is updated with Account Number 123

System.assertEquals('123', [SELECT AccountNumber FROM Account WHERE Id = :a.Id]. AccountNumber); // Rollback to the previous null value Database.rollback(sp);

//Code is rollbacked to savepoint which means account number that we updated will

be rolled back

System.assertEquals(null, [SELECT AccountNumber FROM Account WHERE Id = :a.Id]. AccountNumber);


See one more example below: 

Suppose, There is a scenario where you insert parent with child record from visualforce page.

Case 1 : Unfortunately there was any error in creating child record(like user didn't fill required fields), but parent has been created successfully.

Case 2 : User has filled the required information and clicked on save button again. So in this case there will be two parents created.

Now if you look into data base, there will be two parent records (from case one with no child and from case 2 with a child).

So case one could be avoided by using savepoint and rollback.

The syntax is to set the save point before any dml and then rollback to that savepoint when you face any error.
Savepoint sp = Database.setSavepoint();
try{ insert parent; insert child;
catch(exception ex){
Database.rollback(sp);     }
}
One more example below:
Savepoint sp = Database.setSavepoint();; Account a = new Account(); a.Name='Salesforce Learning Hub'; a.AccountNumber = '123'; insert a; Contact c = new Contact()
c.Account = a.Id; try { insert c; } catch(Exception e) { Database.RollBack(sp); }
In this example, if any error occurs while inserting the Contact 'c', then the entire transaction will be rolled back to savepoint sp ( as specified in the catch section by Database.rollback method).

Some points that needs to be considered:

1) If you set more than one savepoint, then roll back to a savepoint that is not the last savepoint you generated, the later savepoint variables become invalid. For example, if you generated savepoint SP1 first, savepoint SP2 after that, and then you rolled back to SP1, the variable SP2 would no longer be valid. You will receive a runtime error if you try to use it.

2) References to savepoints cannot cross trigger invocations because each trigger invocation is a new trigger context. If you declare a savepoint as a static variable then try to use it across trigger contexts, you will receive a run-time error.

3) Each savepoint you set counts against the governor limit for DML statements.
4) Static variables are not reverted during a rollback. If you try to run the trigger again, the static variables retain the values from the first run.

5) Each rollback counts against the governor limit for DML statements. You will receive a runtime error if you try to rollback the database additional times.

6) The ID on an sObject inserted after setting a savepoint is not cleared after a rollback. Create an sObject to insert after a rollback. Attempting to insert the sObject using the variable created before the rollback fails because the sObject variable has an ID. Updating or upserting the sObject using the same variable also fails because the sObject is not in the database and, thus, cannot be updated.

For more reference please visit:

Friday, October 2, 2020

Implement Lazy Loading in Lightning Datatable

In this article we are going to understand and implement lazy loading used in lightning component to fetch the records from database on demand rather than loading all data at a time.

To reduce or delay expensive calculations or data loading, use lazy loading, a technique in which a page loads its essential features first and delays the rest—either briefly or until the user performs an action that requires the information. This technique gives users faster access to essential features, improving the apparent responsiveness of a large page, even though the entire page takes the same total time to load.

Scenario: We will create a lightning data table which shows list of opportunities, here showing 10 records and when user scrolls down the table it loads more records along with previously fetched records.

Step 1: Create Apex Class LazyOppotunitiesController.apxc

public class LazyOppotunitiesController { @AuraEnabled public Static list<Opportunity> getOpportunity(Integer Limits){ return [Select id, Name, StageName, CloseDate,Account.Name, Amount From Opportunity LIMIT :Integer.valueof(Limits)]; } @AuraEnabled public static Integer totalOpportunitySize(){ AggregateResult results = [SELECT Count(Id) TotalOpportunity From Opportunity]; Integer totalOpportunity = (Integer)results.get('TotalOpportunity'); return totalOpportunity; } }


Step2: Create lightning component

LazyOppotunitiesComponent.cmp

<aura:component controller ="LazyOppotunitiesController" implements="force:appHostable,flexipage:availableForAllPageTypes, flexipage:availableForRecordHome,force:hasRecordId" access="global" > <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <aura:attribute name="columns" type="List" /> <aura:attribute name="Opplist" type="object" /> <aura:attribute name="initRows" type="Integer" default="10"/> <aura:attribute name="Count" type="Integer" default="10"/> <aura:attribute name="totalResultsData" type="Integer" default="0"/> <div class="slds-m-around_xx-small" style="height: 300px"> <lightning:datatable columns="{!v.columns}" data="{!v.Opplist}" keyField="Id" showRowNumberColumn="true" rowNumberOffset="0" enableInfiniteLoading="true" loadMoreOffset="{!v.loadMoreOffset}" onloadmore="{!c.LoadMore}" hideCheckboxColumn="true"/> </div> </aura:component>

LazyOppotunitiesComponentController.js

({ doInit : function(component, event, helper) { component.set('v.columns', [ {label: 'Opportunity name', fieldName: 'Name'}, {label: 'Account name', fieldName: 'AccountName'}, {label: 'Close date', fieldName: 'CloseDate', type: 'date'}, {label: 'Amount', fieldName: 'Amount', type: 'text'}, {label: 'Stage', fieldName: 'StageName', type: 'text'} ]); helper.totalopportunity(component,helper); }, LoadMore:function (component, event, helper) { event.getSource().set("v.isLoading", true); var nextlimit=component.get("v.initRows")+component.get("v.Count"); component.set("v.initRows",nextlimit) var action = component.get("c.getOpportunity"); action.setParams({ "Limits": component.get("v.initRows"), }); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS" ) { var Opplist = response.getReturnValue(); event.getSource().set("v.isLoading", false); component.set('v.Opplist',Opplist); for (var i = 0; i < Opplist.length; i++) { var row = Opplist[i]; if (row.Account) row.AccountName = row.Account.Name; } component.set('v.Opplist', Opplist); } }); if(component.get("v.initRows")<=component.get('v.totalResultsData')) { $A.enqueueAction(action); } else{ if(component.get('v.initRows')-component.get("v.totalResultsData")<component.get("v.Count")){ $A.enqueueAction(action); }else{ event.getSource().set("v.isLoading", false); } } }, })

LazyOppotunitiesComponentHelper.cmp

({

getOpportunityList : function(component,helper) { var action = component.get("c.getOpportunity") action.setParams({ "Limits": component.get("v.initRows")}); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS" ) { var showToast = $A.get("e.force:showToast"); showToast.setParams({ 'title' : 'Load', 'message' : 'Opportunity Loaded Successfully.', 'type': 'Success' }); showToast.fire(); var Opplist = response.getReturnValue(); component.set("v.Opplist",Opplist); for (var i = 0; i < Opplist.length; i++) { var row = Opplist[i]; if (row.Account) row.AccountName = row.Account.Name; } component.set('v.Opplist', Opplist); } }); $A.enqueueAction(action); }, totalopportunity : function(component,helper) { var action = component.get("c.totalOpportunitySize"); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS" ) { var resultData = response.getReturnValue(); component.set("v.totalResultsData",resultData); } }); $A.enqueueAction(action); this.getOpportunityList(component,helper); }, })

Step3: Output of the above code



Thanks for reading..!!

Wednesday, September 23, 2020

Understand Aura Method in Lightning Component


In this article we are going to discuss about aura method used in lightning component to communicate between parent and child component.

With the help of aura method we can directly call a method in component's client side controller instead of firing and handling the component event. Basically we define aura method in child component and let parent component call the aura method of child component from its js controller which in result invoke the action written on aura method inside child component. During this parent can pass values which can be captured in child. Let's see the example below:

auraMethodDemoParent.cmp

<aura:component> <c:auraMethodDemoChild aura:id="compB"/> <lightning:button label="Call child method" onclick="{! c.onAction}" /> </aura:component>

auraMethodDemoParent.js

({ onAction : function(component, event, helper) { var objCompB = component.find('compB'); objCompB.sampleMethod("Param1 from parent", "Param2 from parent"); } })

auraMethodDemoChild.cmp

<aura:component> <!-- sampleMethod(param1, param2)--> <aura:method name="sampleMethod" action="{!c.doAction}" description="Sample method with parameters"> <aura:attribute name="param1" type="String" default="parameter 1"/> <aura:attribute name="param2" type="Object" /> </aura:method> </aura:component>

auraMethodDemoChild.js

({ doAction : function(cmp, event) { var params = event.getParam('arguments'); if (params) { var param1 = params.param1; var param2 = params.param2; alert('Received data from parent in child is '+param1+' and '+ param2); } } })

When parent component clicks on Call Child Method button, we are invoking aura method defined in child component and passing the required attributes which in result execute the onaction method written in child component where parameters passed by parent are retrieved.

Output of the above code:




For more reference please visit the below link:

https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/ref_tag_method.htm


Sunday, September 20, 2020

Bubble Phase and Capture Phase in Lightning Component Event


In this article we are going to understand two phases of lightning component event propagation. We will discuss the difference between both of them with real example.

Bubble phase and capture phase are available in component event in which event can be handled by the component that fired the event or by a component in the containment hierarchy that receives the event.

Bubble Phase:

In bubble phase the component that fired the event can handle it. The event then propagates from source event who fired the event to the application root which is top in the hierarchy, handlers of the components will invoke from bottom to top. It is the default phase if didn't mentioned. 

Capture Phase:

In bubble phase the event is captured and trickles down from application root which is top in hierarchy to the source component, handlers of the components will invoke from bottom to top.


Syntax for defining the phase:

<aura:handler name="cmpEvent" event="c:cmpEvent" action="{!c.handleCmpEvent}" phase="capture"/>
Let's see the real example to understand the flow of events in both the phase 

cmpEvent.evt

<aura:event type="COMPONENT">
    <aura:attribute name="message" type="String"/>
</aura:event>

GrandParentCmp.cmp

<aura:component >

     <!--Bubble Phase-->

<aura:handler name="cmpEvent" event="c:cmpEvent" action="{!c.handleCmpEventInGrandParent}"/>-->

    <!--Capture Phase

    <aura:handler name="cmpEvent" event="c:cmpEvent" action="{!c.handleCmpEventInGrandParent}" phase="capture"/>

-->

    <c:ParentCmp/>

</aura:component>

GrandParentCmp.js

({

handleCmpEventInGrandParent : function(component, event, helper) {

var message = event.getParam("message");

        console.log('Event captured in GrandParent with message '+message);

}

})

ParentCmp.cmp

<aura:component >

    <!--Bubble Phase-->

<aura:handler name="cmpEvent" event="c:cmpEvent" action="{!c.handleCmpEventInParent}"/> -->

     <!--Capture Phase

    <aura:handler name="cmpEvent" event="c:cmpEvent" action="{!c.handleCmpEventInParent}" phase="capture"/>

-->

    <c:ChildCmp/>

</aura:component>

ParentCmp.js

({

handleCmpEventInParent : function(component, event, helper) {

var message = event.getParam("message");

        console.log('Event captured in Parent with message:'+message);

}

})

ChildCmp.cmp

<aura:component >

<aura:registerEvent name="cmpEvent" type="c:cmpEvent"/>

<h1>Simple Component Event Sample</h1>

<p><lightning:button label="Click here to fire a component event"

onclick="{!c.fireComponentEvent}" />

</p> </aura:component>

ChildCmp.js

({

fireComponentEvent : function(cmp, event) {

        var cmpEvent = cmp.getEvent("cmpEvent");

        cmpEvent.setParams({

            "message" : "A component event fired"});

        cmpEvent.fire();

    }

})

Output Of Bubble Phase:



Output Of Capture Phase:



For more reference, please visit:

Fan Switch Example | Understanding Communication between Lightning components

In this article we are going to see a simple FAN switch on/off example. Concept used here are: 1) Parent to child communication using Aura M...