Maximum Trigger Depth Exceeded Error Salesforce

Maximum Trigger Depth Exceeded Error Salesforce

Maximum Trigger Depth Exceeded Error Salesforce occurs mainly due to recursion in the trigger. Recursion can occur because of many reasons. Recursion occurs when the same code is executed again and again. It can lead to an infinite loop and which can result in governor limit sometime. Sometimes it can also result in unexpected output.

In the following trigger, we are checking if contact last name is not equal to SFDC, then we are preparing set of account id. Now let’s assume that we are updating account record in this trigger and there is one more trigger which updates contact record when accounts are updated

trigger SampleTrigger on Contact (after update){
    Set<String> accIdSet = new Set<String>(); 	
    for(Contact conObj : Trigger.New){
        if(conObj.LastName != 'SFDC'){
            accIdSet.add(conObj.accountId);
        }
    }
    // Use accIdSet in some way to update account
}

We will get an error in the above example if there is recursion Maximum Trigger Depth Exceeded Error.

Solution to resolve Maximum Trigger Depth Exceeded Error Salesforce

To avoid these kind of situation we can use public class static variable. We can solve this issue, you can set a condition on trigger so it will not be called recursively.

In RecursiveTriggerHandler class, we have a static variable that is set to true by default.

public class RecursiveTriggerHandler{
    public static Boolean isFirstTime = true;
}

In the following trigger, we are checking if the static variable is true only then trigger runs. Also, we are setting a static variable to false when trigger runs for the first time. So if the trigger will try to run second time in the same request then it will not run.

trigger SampleTrigger on Contact (after update){
    Set<String> accIdSet = new Set<String>();
    if(RecursiveTriggerHandler.isFirstTime){
        RecursiveTriggerHandler.isFirstTime = false;
        for(Contact conObj : Trigger.New){
            if(conObj.name != 'SFDC'){
                accIdSet.add(conObj.accountId);
            }
        }
        // Use accIdSet in some way to update account
    }
}

For more details refer to Avoid recursive trigger in salesforce using static variable

Permanent link to this article: https://www.sfdcpoint.com/salesforce/maximum-trigger-depth-exceeded-error-salesforce/

Triggers in Salesforce

Apex Triggers in Salesforce

Apex Triggers in Salesforce

What is Triggers in Salesforce?

A trigger is an Apex script that executes before or after data manipulation language (DML) events occur. Apex triggers enable you to perform custom actions before or after events to record in Salesforce, such as insertions, updates, or deletions. Just like database systems support triggers, Apex provides trigger support for managing records.

Triggers in Salesforce

 

When to use salesforce triggers

We should use triggers to perform tasks that can’t be done by using the point-and-click tools in the Salesforce user interface. For example, if validating a field value or updating a field on a record, use validation rules and workflow rules instead.

What is Trigger Syntax?

trigger TriggerName on ObjectName (trigger_events) {
   code_block
}

Trigger events in salesforce?

A trigger is a set of statement which can be executed on the following events. In above trigger events one or more of below events can be used with comma-separated.

Here is a list of trigger events in salesforce

  • before insert
  • before update
  • before delete
  • after insert
  • after update
  • after delete
  • after undelete

What are different type of Triggers?

There are two types of triggers:

  • Before triggers are used to perform a task before a record is inserted or updated or deleted. These are used to update or validate record values before they are saved to the database.
  • After triggers are used if we want to use the information set by Salesforce system and to make changes in the other records. are used to access field values that are set by the system (such as a record’s Id or LastModifiedDate field), and to affect changes in other records. The records that fire the after trigger are read-only.

What are the considerations while implementing the Triggers?

Consider the following before implementing the triggers.

  • Upsert trigger fires on 4 different events :- before(insert, update), after (insert, update)
  • Merge trigger are fired on both events on delete
  • Field history is updated after the trigger has successfully finished processing data.
  • Any callout should be asynchronous so that trigger does not have to wait for the response.
  • A trigger cannot have a static keyword in its code.
  • If a trigger completes successfully the changes are committed to the database and if it fails the transaction is rolled back.

Read the Apex Developer Guide for more detailed considerations.

What are context variables in triggers?

All triggers define implicit variables that allow developers to access run-time context. These variables are contained in the System.Trigger class.

Here is list of context variables in triggers

  • isExecuting: Returns true if the current context for the Apex code is a trigger, not a Visualforce page, a Web service, or an executeanonymous() API call.
  • isInsert: Returns true if this trigger was fired due to an insert operation, from the Salesforce user interface, Apex, or the API.
  • isUpdate: Returns true if this trigger was fired due to an update operation, from the Salesforce user interface, Apex, or the API.
  • isDelete: Returns true if this trigger was fired due to a delete operation, from the Salesforce user interface, Apex, or the API.
  • isBefore: Returns true if this trigger was fired before any record was saved.
  • isAfter: Returns true if this trigger was fired after all records were saved.
  • isUndelete: Returns true if this trigger was fired after a record is recovered from the Recycle Bin (that is, after an undelete operation from the Salesforce user interface, Apex, or the API.)
  • new: Returns a list of the new versions of the sObject records. This sObject list is only available in insert, update, and undelete triggers, and the records can only be modified in before triggers.
  • newMap: A map of IDs to the new versions of the sObject records. This map is only available in before update, after insert, after update, and after undelete triggers.
  • old : Returns a list of the old versions of the sObject records. This sObject list is only available in update and delete triggers.
  • oldMap: A map of IDs to the old versions of the sObject records. This map is only available in update and delete triggers.
  • size: The total number of records in a trigger invocation, both old and new.

Refer to Trigger context variables in salesforce link for more details.

Context Variable Considerations

Trigger EventCan change fields using trigger.newCan update original object using an update DML operationCan delete original object using a delete DML operation
before insertAllowed.Not applicable. The original object has not been created; nothing can reference it, so nothing can update it.Not applicable. The original object has not been created; nothing can reference it, so nothing can update it.
after insertNot allowed. A runtime error is thrown, as trigger.new is already saved.Allowed.Allowed, but unnecessary. The object is deleted immediately after being inserted.
before updateAllowed.Not allowed. A runtime error is thrown.Not allowed. A runtime error is thrown.
after updateNot allowed. A runtime error is thrown, as trigger.new is already saved.Allowed. Even though bad code could cause an infinite recursion doing this incorrectly, the error would be found by the governor limits.Allowed. The updates are saved before the object is deleted, so if the object is undeleted, the updates become visible.
before deleteNot allowed. A runtime error is thrown. trigger.new is not available in before delete triggers.Allowed. The updates are saved before the object is deleted, so if the object is undeleted, the updates become visible.Not allowed. A runtime error is thrown. The deletion is already in progress.
after deleteNot allowed. A runtime error is thrown. trigger.new is not available in after delete triggers.Not applicable. The object has already been deleted.Not applicable. The object has already been deleted.
after undeleteNot allowed. A runtime error is thrown.Allowed.Allowed, but unnecessary. The object is deleted immediately after being inserted.

Salesforce Trigger Example

before insert trigger salesforce

Account trigger to set account rating as ‘Hot’ if account industry is ‘Banking’ or ‘Healthcare’

before update trigger salesforce

trigger AccountCustomTrigger on Account (before insert, before update) {
    for(Account acc : Trigger.New) {
        if(acc.Industry != null && (acc.Industry == 'Banking' || acc.Industry == 'Healthcare')){
         acc.Rating = 'Hot';
        }
    }
}

Please note that in the above example we are not manually updating accounts using DML statement as it is before insert or before update trigger.

after insert trigger salesforce

Let us see one more example of a trigger on contact which will create Account record whenever contact is created without an account.

trigger ContactCustomTriggerExample on Contact (after insert) {
    List<Account> accListToInsert = new List<Account>();
    for(Contact con : Trigger.New) {
        //check if account is null on contact
        if(con.AccountId == null ) {
            Account acc = new Account();
            //Add all required field on Account
            acc.Name = con.LastName;
            acc.Phone = con.Phone;
            accListToInsert.add(acc);
        }
    }
    if(!accListToInsert.isEmpty()){
    insert accListToInsert;
    }
} 

Define Recursive Trigger and how to avoid it?

There is a possibility that the result of the trigger can end up calling the same trigger again and can run in a loop, this is known as a recursive trigger. To avoid this scenario we should create a static variable and check the value of this variable before we execute anything in the trigger. For more details refer to below link:

Avoid recursive trigger in salesforce

What do you mean by the bulkifying trigger?

A trigger should be able to handle single record and thousands of record. There are two important point for bulkifying trigger:

  • Write triggers that operate on collections of sObjects.
  • Write triggers that perform efficient SOQL and DML operations.

If we will not follow above point we may hit governor limit when records are created/updated/deleted in mass using data loader or other tool.

Bulk Apex Trigger trailhead

For more detail about trigger in salesforce refer Official link

For interview questions related to salesforce refer to  Salesforce Interview Questions on Triggers

Permanent link to this article: https://www.sfdcpoint.com/salesforce/apex-trigger-in-salesforce/

aura method in lightning salesforce

aura method in lightning salesforce

aura method in lightning salesforce

Use aura:method to define a method as part of a component’s API. This enables you to directly call a method in a component’s client-side controller instead of firing and handling a component event. Using aura:method simplifies the code needed for a parent component to call a method on a child component that it contains.

Here is a list of attributes for aura method in lightning salesforce

AttributeTypeDescription
nameStringThe method name. Use the method name to call the method in JavaScript code.
actionExpressionThe client-side controller action to execute.
accessStringThe access control for the method. Valid values are:
public—Any component in the same namespace can call the method. This is the default access level.
global—Any component in any namespace can call the method.
descriptionStringThe method description.

An aura:method can optionally include parameters. Use an aura:attribute tag within an aura:method to declare a parameter for the method.

Example of aura:method

In this example, we are creating a Child component aura method with two parameters. These two parameters are ‘childGreetingParam’ and ‘ChildPersonName’. These parameters are having a default value of ‘Hello’ and ‘World’ respectively.

ChildComponent

<aura:component>
    <aura:method name="childMessageMethod" action="{!c.getMessage}" access="public">
        <aura:attribute name="childGreetingParam" type="String" default="Hello"/> 
        <aura:attribute name="childPersonNameParam" type="String" default="World"/> 
    </aura:method>
</aura:component>

ChildComponentController

In Child Component controller, we are getting the value of parameters and showing alert.

({
    getMessage : function(component, event) {
        //get method paramaters
        var params = event.getParam('arguments');
        if (params) {
            var param1 = params.childGreetingParam;
            var param2 = params.childPersonNameParam;
            alert(param1 + " " + param2);
        }
    }
})

ParentComponent

In the parent component, child component is added and button for calling parent component controller method.

<!--Parent cmp-->
<aura:component>  
    <div class="slds-m-around_xx-large">
        <!-- Add Child Component -->
        <c:ChildComponent aura:id="childCmp"/>
        <!-- On button click child aura:method will be called-->
        <lightning:button variant="brand" label="Call Child" onclick="{!c.callAuraMethod}" />
    </div>
</aura:component>

ParentComponentController

In ParentComponetController, we are simply finding child component and calling its aura method.

({
    callAuraMethod : function(component, event, helper) {
        //Call Child aura method
        var childComponent = component.find("childCmp");
        var message = childComponent.childMessageMethod();
    }
})

Using AuraMethodSample app for testing

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

Here is output when user clicks on Call child button. Output is ‘Hello World’ because no value of parameter is passed. So it is showing default value.

aura method in lightning salesforce

In the above example, we are using parameters of the child component. We can also pass parameters from parent component to child component like this:

({
    callAuraMethod : function(component, event, helper) {
        //Call Child aura method
        var childComponent = component.find("childCmp");
        var message = childComponent.childMessageMethod('Happy Coding','Readers');
    }
})

Now when the user will click on the ‘Call Child’ button on the parent component. The output will be ‘Happy Coding Readers’ instead of ‘Hello World’ because we are passing the value of attributes.

aura:method always executes synchronously so method execution finishes before it returns.

For more details please refer below link https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/ref_tag_method.htm

For more post related to salesforce lightning refer Salesforce lightning sfdcpoint link

Happy Coding 🙂

Permanent link to this article: https://www.sfdcpoint.com/salesforce/aura-method-in-lightning-salesforce/

salesforce order of execution

Salesforce order of execution

What is salesforce order of execution?

What is order of execution in salesforce?

Salesforce order of execution

When you save a record with an insertupdate, or upsert statement, Salesforce performs the following events in order.

Before Salesforce executes these events on the server, the browser runs JavaScript validation if the record contains any dependent picklist fields. The validation limits each dependent picklist field to its available values. No other validation occurs on the client side.

Salesforce order of execution

Salesforce order of execution

 

Here is an order of execution in salesforce

  • The original record is loaded from the database.
  • System Validation Rules.
  • Executes record-triggered flows that are configured to run before the record is saved.
  • Executes all before triggers.
  • Custom Validation rules.
  • Executes duplicate rules.
  • Saves the record to the database, but doesn’t commit yet.
  • Executes all after triggers.
  • Executes assignment rules.
  • Executes auto-response rules.
  • Executes workflow rules. If there are workflow field updates, updates the record again.
  • If the record was updated with workflow field updates, fires before and after triggers one more time. Custom validation rules, flows, duplicate rules, processes, and escalation rules are not run again.
  • Executes escalation rules.
  • Executes processes and flows launched via processes and flow trigger workflow actions.
  • Executes entitlement rules.
  • Executes record-triggered flows that are configured to run after the record is saved.
  • If the record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the parent record. Parent record goes through save procedure.
  • If the parent record is updated, and a grandparent record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the grandparent record. Grandparent record goes through save procedure.
  • Executes Criteria Based Sharing evaluation.
  • Commits all DML operations to the database.
  • Executes post-commit logic, such as sending email.

 

Here is an order of execution in salesforce in more detail:

On the salesforce server,

  1. Loads the original record from the database or initializes the record for an upsert statement.
  2. Loads the new record field values from the request and overwrites the old values.

    If the request came from a standard UI edit page, Salesforce runs system validation to check the record for:

    • Compliance with layout-specific rules
    • Required values at the layout level and field-definition level
    • Valid field formats
    • Maximum field length

    When the request comes from other sources, such as an Apex application or a SOAP API call, Salesforce validates only the foreign keys. Before executing a trigger, Salesforce verifies that any custom foreign keys do not refer to the object itself.

    Salesforce runs user-defined validation rules if multiline items were created, such as quote line items and opportunity line items.

  3. Executes record-triggered flows that are configured to run before the record is saved.
  4. Executes all before triggers.
  5. Runs most system validation steps again, such as verifying that all required fields have a non-null value, and runs any user-defined validation rules. The only system validation that Salesforce doesn’t run a second time (when the request comes from a standard UI edit page) is the enforcement of layout-specific rules.
  6. Executes duplicate rules. If the duplicate rule identifies the record as a duplicate and uses the block action, the record is not saved and no further steps, such as after triggers and workflow rules, are taken.
  7. Saves the record to the database, but doesn’t commit yet.
  8. Executes all after triggers.
  9. Executes assignment rules.
  10. Executes auto-response rules.
  11. Executes workflow rules. If there are workflow field updates
    • Updates the record again.
    • Runs system validations again. Custom validation rules, flows, duplicate rules, processes, and escalation rules are not run again.
    • Executes before update triggers and after update triggers, regardless of the record operation (insert or update), one more time (and only one more time)

     

  12. Executes escalation rules.
  13. Executes the following Salesforce Flow automations, but not in a guaranteed order.
    • Processes
    • Flows launched by processes
    • Flows launched by workflow rules (flow trigger workflow actions pilot)

    When a process or flow executes a DML operation, the affected record goes through the save procedure.

  14. Executes entitlement rules.
  15. Executes record-triggered flows that are configured to run after the record is saved.
  16. If the record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the parent record. Parent record goes through save procedure.
  17. If the parent record is updated, and a grandparent record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the grandparent record. Grandparent record goes through save procedure.
  18. Executes Criteria Based Sharing evaluation.
  19. Commits all DML operations to the database.
  20. After the changes are committed to the database, executes post-commit logic such as sending email and executing enqueued asynchronous Apex jobs, including queueable jobs and future methods.

Additional Considerations

Note the following when working with triggers.

  • If a workflow rule field update is triggered by a record update, Trigger.old doesn’t hold the newly updated field by the workflow after the update. Instead Trigger.old holds the object before the initial record update was made. For example, an existing record has a number field with an initial value of 1. A user updates this field to 10, and a workflow rule field update fires and increments it to 11. In the update trigger that fires after the workflow field update, the field value of the object obtained from Trigger.old is the original value of 1, and not 10.
  • If a DML call is made with partial success allowed, triggers are fired during the first attempt and are fired again during subsequent attempts. Because these trigger invocations are part of the same transaction, static class variables that are accessed by the trigger aren’t reset.
  • The order of execution isn’t guaranteed when having multiple triggers for the same object due to the same event. For example, if you have two before insert triggers for Case, and a new Case record is inserted that fires the two triggers, the order in which these triggers fire isn’t guaranteed.
  • If an object has multiple active record-triggered flows that are configured to run before or after the record is saved, the order in which those flows are executed isn’t guaranteed.
  • To learn about the order of execution when you insert a non-private contact in your org that associates a contact to multiple accounts, see AccountContactRelation.

Please refer to below official link for salesforce order of execution:

Trigger and Order of Execution

For interview questions related to trigger, refer to the below link:

Salesforce Interview Questions on Triggers

Permanent link to this article: https://www.sfdcpoint.com/salesforce/salesforce-order-of-execution/

Guest Post

Guest Post sfdcpoint

Guest Post to sfdcpoint.com Want to contribute an article to sfdcpoint.com? Please share your post to dureja.ankush90@gmail.com. Purpose of sfdcpoint.com is to share knowledge with salesforce community. So all of you are welcome to post your article on sfdcpoint.com.

Here are some of tips for post:

  • Article Quality : Try to write an article with more than 300 words.
  • Screenshot: Sometime image speaks more than words. So its advisable to add some screenshot.
  • Video: If possible, add some video for demo. Its not necessary.

Send your article to dureja.ankush90@gmail.com with subject line sfdcpoint guest post. We will review your post. Once approved we will post your article to sfdcpoint with your name. You will also be rewarded with some goodies.

Good Luck 🙂

 

 

Permanent link to this article: https://www.sfdcpoint.com/salesforce/guest-post/

Modal/Popup Lightning Component Salesforce

Modal/Popup Lightning Component Salesforce

Modal/Popup Lightning Component Salesforce

In this post, We will simply create a custom Lightning Modal/Popup Box in the salesforce lightning component.

What is Modal in Salesforce Lightning Experience ?

Modals/Popup Box are used to display content in a layer above the app. This paradigm is used in cases such as the creation or editing of a record, as well as various types of messaging and wizards.

Modal/Popup Lightning Component Salesforce looks like following image

Modal Popup Lightning Component Salesforce

Modal Popup Lightning Component Salesforce

 

ModalPopupExample1 Lightning  Component

In this code we are first declaring ‘isModalOpen’ attribute and setting its default value as false. Then using aura:if we are conditionally displaying modal/popup on click of button. For more details about aura:if, please refer my previous post aura:if in lightning component example

Also code has following three main part

  • section
  • header
  • footer

Details are explained in code comment.

Following is expected markup

Expected markup in in modal/popup

  • Modal has role="dialog"
  • When the modal is open, everything behind it has HTML attribute aria-hidden="true", so assistive technology won’t read out the underlying page. The best way to do this is to give the modal and the page separate wrapper elements and toggle aria-hidden="true"/aria-hidden="false" on the main page’s wrapper depending on whether or not the modal is open.
  • Modal contains an HTML heading
  • Modal has an aria-labelledby attribute whose value is the id of the modal’s heading

 

<aura:component>
    <!--Boolean attribute to indicate if modal is open or not 
       default value is false as modal is closed when page is loaded 
    --> 
    <aura:attribute name="isModalOpen" type="boolean" default="false"/>
    
    <div class="slds-m-around_xx-large">
        <lightning:button variant="brand"
                          label="What is Modal/PopUp Box?"
                          title="What is Modal/PopUp Box?"
                          onclick="{! c.openModel }" />
        <!--Use aura:if tag to display/hide popup based on isModalOpen value-->   
        <aura:if isTrue="{!v.isModalOpen}">
            
            <!-- Modal/Popup Box starts here--> 
            <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
                <div class="slds-modal__container">
                    <!-- Modal/Popup Box Header Starts here-->
                    <header class="slds-modal__header">
                        <lightning:buttonIcon iconName="utility:close"
                                              onclick="{! c.closeModel }"
                                              alternativeText="close"
                                              variant="bare-inverse"
                                              class="slds-modal__close"/>
                        <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Modal/PopUp Box</h2>
                    </header>
                    <!--Modal/Popup Box Body Starts here-->
                    <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                        <p><b>Modals/Popup Box are used to display content in a layer above the app. This paradigm is used in cases such as the creation or editing of a record, as well as various types of messaging and wizards.
                            </b>
                        </p>
                    </div>
                    <!--Modal/Popup Box Footer Starts here-->
                    <footer class="slds-modal__footer">
                        <lightning:button variant="neutral" 
                                          label="Cancel"
                                          title="Cancel"
                                          onclick="{! c.closeModel }"/>
                        <lightning:button variant="brand" 
                                          label="OK"
                                          title="OK"
                                          onclick="{!c.submitDetails}"/>
                    </footer>
                </div>
            </section>
            <div class="slds-backdrop slds-backdrop_open"></div>
        </aura:if>
    </div>
</aura:component>

Lightning Component Controller

({
   openModel: function(component, event, helper) {
      // Set isModalOpen attribute to true
      component.set("v.isModalOpen", true);
   },
 
   closeModel: function(component, event, helper) {
      // Set isModalOpen attribute to false  
      component.set("v.isModalOpen", false);
   },
 
   submitDetails: function(component, event, helper) {
      // Set isModalOpen attribute to false
      //Add your code to call apex method or do some processing
      component.set("v.isModalOpen", false);
   },
})

Lightning component App ModalPopupExampleApp1

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

More details about lightning modal/popup

Modals always have an equal amount of space at the top and bottom to account for the height of the close button.

Modals grow according to how much content is within, but once the modal reaches full height (including the previously mentioned space on top and bottom), the content area will begin to scroll. (This scrolling is currently not available in Salesforce1 Mobile.)

For more details about modal in lightning, please refer to modal lightning

 

Permanent link to this article: https://www.sfdcpoint.com/salesforce/modal-popup-lightning-component-salesforce/

Lightning Datatable example salesforce

Lightning Datatable example salesforce

Lightning Datatable example salesforce

In this blog post, I am going to explain how to use salesforce lightning:datatable component and its features. A lightning:datatable component displays tabular data where each column can be displayed based on the data type. lightning:datatable also supports inline editing. lightning:datatable is not supported on mobile devices.

Lightning Datatable Main Features

  • Displaying and formatting of columns with appropriate data types
  • Infinite scrolling of rows
  • Inline editing for some data types
  • Header-level actions
  • Row-level actions
  • Resizing of columns
  • Selecting of rows
  • Sorting of columns by ascending and descending order
  • Text wrapping and clipping
  • Row numbering column
  • Cell content alignment

 

Tables can be populated during initialization using the data, columns, and keyField attributes. The keyField attribute is required for correct table behavior. It will associate each row with a unique identifier. The below code shows how to use the lightning: datatable to initialize the data and columns which are passed by using attributes.

Lightning Datatable Example

In this example, we will simply display list of account using lightning:datatable.

Apex class AccountController

public class AccountController{
    @AuraEnabled
    public static List <Account> fetchAccounts() {
        //Qyery 10 accounts
        List<Account> accList = [SELECT Id, Name, BillingState, 
                                    Website, Phone, Industry, Type from Account LIMIT 10];
        //return list of accounts
        return accList;
    }
}

Lightning Component LightningDatatableExample

<aura:component controller="AccountController">
     
    <aura:attribute type="Account[]" name="acctList"/>
    <aura:attribute name="mycolumns" type="List"/>
     
    <aura:handler name="init" value="{!this}" action="{!c.fetchAcc}"/>
     
    <lightning:datatable data="{! v.acctList }"
                         columns="{! v.mycolumns }"
                         keyField="id"
                         hideCheckboxColumn="true"/>
     
</aura:component>

Lightning Component LightningDatatableExample Controller

({
    fetchAcc : function(component, event, helper) {
        helper.fetchAccHelper(component, event, helper);
    }
})

Lightning Component LightningDatatableExample Helper

({
	fetchAccHelper : function(component, event, helper) {
        component.set('v.mycolumns', [
            {label: 'Account Name', fieldName: 'Name', type: 'text'},
                {label: 'Industry', fieldName: 'Industry', type: 'text'},
                {label: 'Phone', fieldName: 'Phone', type: 'Phone'},
                {label: 'Website', fieldName: 'Website', type: 'url '}
            ]);
        var action = component.get("c.fetchAccounts");
        action.setParams({
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.acctList", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    }
})

Lightning Application LightningDatatableExample

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

 

Lightning Datatable example Output

Lightning Datatable example salesforce output

Lightning Datatable example salesforce output

 

Lightning Datatable Column Properties

Use the following column properties to customize the behavior and visual aspects of your columns.

PROPERTYTYPEDESCRIPTION
actionsobjectAppends a dropdown menu of actions to a column. You must pass in a list of label-name pairs.
cellAttributesobjectProvides additional customization, such as horizontal alignment or appending an icon to the output. For more information about alignment, see Aligning Data in a Column. For more information about adding icons, see Appending an Icon to Column Data.
editablebooleanSpecifies whether a column supports inline editing. The default is false.
fieldNamestringRequired. The name that binds the columns properties to the associated data. Each columns property must correspond to an item in the data array.
fixedWidthintegerSpecifies the width of a column in pixels and makes the column non-resizable.
iconNamestringThe Lightning Design System name of the icon. Names are written in the format standard:opportunity. The icon is appended to the left of the header label.
initialWidthintegerThe width of the column when it's initialized, which must be within the minColumnWidth and maxColumnWidth values, or within 50px and 1000px if they are not provided.
labelstringRequired. The text label displayed in the column header.
sortablebooleanSpecifies whether the column can be sorted. The default is false.
typestringRequired. The data type to be used for data formatting. For more information, see Formatting with Data Types.
typeAttributesobjectProvides custom formatting with component attributes for the data type. For example, currencyCode for the currency type. For more information, see Formatting with Data Types.

For more details please refer below official link lightning datatable

Happy Coding 🙂

Permanent link to this article: https://www.sfdcpoint.com/salesforce/lightning-datatable-example-salesforce/

Difference between WhoId and WhatId

Difference between WhoId and WhatId

What is difference between WhoId and WhatId?

Difference between WhoId and WhatId

  • WhoID in Salesforce refers to people things. So that would be typically a Lead ID or a Contact ID. The WhoId represents a human such as a lead or a contact. WhoIds are polymorphic. Polymorphic means a WhoId is equivalent to a contact’s ID or a lead’s ID. The label is Name.

 

  • WhatID in Salesforce refers to object type things.  That would typically be an Account ID or an Opportunity ID. The WhatId represents nonhuman objects such as accounts, opportunities, campaigns, cases, or custom objects. WhatIds are polymorphic. Polymorphic means a WhatId is equivalent to the ID of a related object. The label is Related To.

 

Please check below image for the object diagram:

Difference between WhoId and WhatId

Difference between WhoId and WhatId

 

These fields are available on Task and Event Object. In SOQL query these fields can simply be queries similar to other fields.

For more details refer to below link https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_erd_activities.htm

Happy Coding:)

 

 

Permanent link to this article: https://www.sfdcpoint.com/salesforce/difference-between-whoid-and-whatid/

Use Lightning Components in Visualforce Pages

Use Lightning Components in Visualforce Pages

Use Lightning Components in Visualforce Pages

How To Display Lightning Component In Visualforce Page

In this post, we will see how we can use Lightning Components in Visualforce Pages or how to display Lightning Component In Visualforce Page. Even though the use of lightning is growing day by day, still some customers are using salesforce classic because of many reasons. Sometimes there is a requirement to use lightning component in visualforce page.

Lightning Components for Visualforce is based on Lightning Out, a powerful and flexible feature that lets you embed Lightning components into almost any web page. When used with Visualforce, some of the details become simpler. For example, you don’t need to deal with authentication, and you don’t need to configure a Connected App.

In this example, we will see a very basic example of the lightning component and then display lightning component in the visualforce page.

Lightning Component LightExample1

<aura:component>
    <div>
        <h1> This is lightning component for visualforce page</h1>
    </div>
</aura:component>

Lightning App LightExampleApp1

Here important point is that ltng:outApp needs to be extended in app.

ltng:outApp adds SLDS resources to the page to allow our Lightning components to be styled with the Salesforce Lightning Design System. If we don’t want SLDS resources added to the page, we need to extend from ltng:outAppUnstyled instead.

<aura:application extends="ltng:outApp" access="GLOBAL">
    <aura:dependency resource="c:LightExample1" />
</aura:application>

Visualforce page LightningExampleVF1

<apex:page showHeader="false" sidebar="false">
    <apex:includeLightning />    
    <apex:includeScript value="/lightning/lightning.out.js" />
    <div id="LightningComponentid" />    
    <script>
    $Lightning.use("c:LightExampleApp1", function() {
        $Lightning.createComponent("c:LightExample1",
          { 
          },
          "LightningComponentid",
          function(cmp) {
             console.log('Display Lightning component in visualforce page');
          });
    });
    </script>
</apex:page>

Use Lightning Components in Visualforce Pages output

Use Lightning Components in Visualforce Pages output

Use Lightning Components in Visualforce Pages output

 

In the above Visualforce page, apex:includeLightning tag imports necessary dependencies and scripts to enable Visualforce to act as Lightning component container.

We can use $Lightning.use() method in JavaScript to refer to Lightning Application which extends ltng:outApp.

We can use $Lightning.createComponent create Lightning Component dynamically.

We can call $Lightning.use() multiple times on a page, but all calls must reference the same Lightning dependency app.

Other Useful links:

We can also pass parameters from visualforce page to lightning component. Check wrapper class in lightning component salesforce link.

For more details please refer the official documentation link

Please check Salesforce lightning link for more posts related to lightning.

Permanent link to this article: https://www.sfdcpoint.com/salesforce/use-lightning-components-in-visualforce-pages/

wrapper class in lightning component salesforce

wrapper class in lightning component salesforce

wrapper class in lightning component salesforce

A wrapper or container class is a class, a data structure, or an abstract data type which contains different objects or collection of objects as its members. In this post we will see how we can use wrapper class in lightning component to display data in lightning component. For details about how we can use wrapper class in visualforce page  check wrapper class in Apex

Let’s see an example of wrapper class in lightning component salesforce. In this example, we will create AcoountContactWrapper and will display account and contact details and display on lightning component.

Apex class controller with the wrapper class

AccountContactController.cls

public class AccountContactController{
    
    @AuraEnabled
    public static AccountContactListWrapper getAccountWithContacts(String accountId){
        AccountContactListWrapper accWrapper = new AccountContactListWrapper();
        List<Account> accList = [SELECT Id, Name, BillingState, Website, Phone,
                                    (SELECT Id, FirstName, LastName, Email From Contacts)
                                    FROM Account WHERE Id =: accountId];
        if(!accList.isEmpty()){
            accWrapper.accRecord = accList[0];
            accWrapper.contactList = accList[0].Contacts;
            accWrapper.contactCount = accList[0].Contacts.size();
        }
        return accWrapper;
    }
    
    // wrapper class with @AuraEnabled and {get;set;} properties 
    public class AccountContactListWrapper{
        @AuraEnabled 
        public Account accRecord{get;set;}
        @AuraEnabled 
        public List<Contact> contactList{get;set;}
        @AuraEnabled 
        public Integer contactCount{get;set;}
    }
}

Lightning component AccountContactWrapperExample

<aura:component controller="AccountContactController" implements="force:hasRecordId">  
    <aura:handler name="init" value="{!this}" action="{!c.initData}"/>
    <!-- Attributes declaration-->  
    <aura:attribute name="accountContactWrapper" type="object"/>
    <aura:attribute name="recordId" type="Id" />
    
    <div class="slds-p-around--large">
        <h1 style="font-size:25px;">{!v.accountContactWrapper.accRecord.Name}</h1> 
        <br/>
        <p style="color:red">Total Contacts = {!v.accountContactWrapper.contactCount}</p>
        
    <table class="slds-table slds-table--bordered slds-table--cell-buffer">
        <thead>
            <tr class="slds-text-title--caps">
                <th scope="col">
                    <div class="slds-truncate" title="First Name">First Name</div>
                </th>
                <th scope="col">
                    <div class="slds-truncate" title="First Name">Last Name</div>
                </th>
                <th scope="col">
                    <div class="slds-truncate" title="Email">Email</div>
                </th>
            </tr>
        </thead>
        <tbody>
            <aura:iteration items="{!v.accountContactWrapper.contactList }" var="con">
                <tr>
                    <th scope="row">
                        <div class="slds-truncate" title="{!con.FirstName}">{!con.FirstName}</div>
                    </th>
                    <th scope="row">
                        <div class="slds-truncate" title="{!con.LastName}">{!con.LastName}</div>
                    </th>
                    <th scope="row">
                        <div class="slds-truncate" title="{!con.Email}">{!con.Email}</div>
                    </th>
                </tr>
            </aura:iteration>
        </tbody>
    </table>
  </div>
</aura:component>

Javascript controller for lightning component AccountContactWrapperExample

({
    initData: function(component, event, helper) {
        console.log('***In controller');
        helper.getAccountContactWrapperhelper(component, event, helper);
    },
})

Helper for lightning component AccountContactWrapperExample

({
    getAccountContactWrapperhelper: function(component, event, helper) {
      console.log('***In helper');
      var a= component.get("v.recordId");
      console.log('***In helper'+a);
      //call apex class method
      var action = component.get('c.getAccountWithContacts');
        action.setParams({
            accountId : component.get("v.recordId")
        });
      action.setCallback(this, function(response) {
        //store state of response
        var state = response.getState();
        if (state === "SUCCESS") {
          //set response value in wrapperList attribute on component.
          component.set('v.accountContactWrapper', response.getReturnValue());
        }
      });
      $A.enqueueAction(action);
    },
})

Lightning App AccountContactWrapperExampleApp

<aura:application access="GLOBAL" extends="ltng:outApp">
    <aura:dependency resource="c:AccountContactWrapperExample"/>
</aura:application>

Visualforce page AccountContactWrapperExampleVF

<apex:page showHeader="false">
    <apex:includeLightning />    
    <apex:includeScript value="/lightning/lightning.out.js" />
    
    <div id="accountContactWrapperId" >
    </div>
    
    <script>
    $Lightning.use("c:AccountContactWrapperExampleApp", function() {
        $Lightning.createComponent("c:AccountContactWrapperExample",{ 
        recordId :"{!$CurrentPage.Parameters.id}"
        },
        "accountContactWrapperId",
        function(cmp) {
        console.log('Display Lightning component in visualforce page');
        });
    });
    </script>

</apex:page>

Testing visualforce page by passing record id in parameter. In my case URL is:

https://pointnew-dev-ed–c.visualforce.com/apex/AccountContactWrapperExampleVF?Id=0011t000008gSnI

Output will be like this:

wrapper class in lightning component salesforce output

wrapper class in lightning component salesforce output

 

Important: Previously it was possible to use inner wrapper class attribute like this:

<aura:attribute name="accountContactWrapper" type="AccountContactController.AccountContactListWrapper"/>

Problem is Lightning components can’t use inner classes as attribute type when the org has setup a namespace. For more details refer below known issue link.

https://success.salesforce.com/issues_view?id=a1p3A0000001CBeQAM

But now it does not work and we have to use Object as type.

<aura:attribute name="accountContactWrapper" type="object"/>

Happy Coding:)

Permanent link to this article: https://www.sfdcpoint.com/salesforce/wrapper-class-in-lightning-component-salesforce/