trigger in Salesforce

Episode 5 – Demystifying Apex Triggers

Apex, Apex Hours for Students, Salesforce Developer Training

In this episode we will learn about writing triggers to fire business logic using Apex. Join us as you embark on this wonderful journey to become a champion Salesforce developer.

Agenda

  • Order of Execution
  • When & How Triggers are invoked
  • Trigger Events
  • Avoiding Recursive Trigger Calls
  • Q & A

Most importantly don’t break a leg if you are overwhelmed with the pace of the live sessions. All Apex Hours for Student sessions will be recorded and will be available on our YouTube channel.

Please register here and follow our ApexHours website to get more notification.

What is Trigger?

Trigger is a procedure in database which automatically invokes whenever a special events in Database occurs. Apex triggers enable you to perform custom actions before or after events to records in Salesforce, such as insertions, updates, or deletions.

Apex Triggers
Apex Triggers

When Should we Use Trigger?

  • Complex logic incapable of being processed via declarative artifacts
  • Logic associated with DML
  • Operations on unrelated objects
  • Integration with External Systems

Trigger Events

Trigger Events
Trigger Events

Trigger Context Variable

Variable Usage
isExecuting It tells if code current context is trigger or not
isInsert It returns true if trigger fires on insert operation
isUpdate It returns true if trigger fires on update operation
isDelete It returns true if trigger fires on delete operation
isBefore It returns true if code is running in Before context
isAfter It returns true if code is running in After context
new It holds list of new versions of 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 It holds new versions of sObject in key value pair
This map is only available in before update, after insert, after update, and after undelete triggers
old It holds list of old versions of sObject records
This sObject list is only available in update and delete triggers
oldMap It holds old versions of sObject in key value pair
This map is only available in update and delete triggers.
operationType Returns an enum of type System.TriggerOperation corresponding to the current operation. System.TriggerOperation enum are: BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE,AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE, and AFTER_UNDELETE
size The total number of records in a trigger invocation, both old and new.

Demo 1 : Using context variable in Trigger

trigger AccountTrigger on Account (before insert, before update, after update) {
    if(Trigger.isBefore && Trigger.isInsert){
        System.debug('I am in AccountTrigger before insert context');
    }
    if(Trigger.isUpdate){
        if(Trigger.isBefore){
            for(Account acc :Trigger.new){
                System.debug('New Name'+ acc.Name);
                System.debug('Old Name'+ Trigger.oldMap.get(acc.Id).Name);
            }
        }
    }
}

Order of Execution.

Order of Execution
Order of Execution

Here is recording of our old session on Order of Execution. Check this blog post to learn more.

Trigger Handler pattern

Check this blog post to learn about which all trigger pattern are available in Salesforce. For Trigger Handler code check this post

Trigger Handler pattern
Trigger Handler Pattern

Trigger Best Practice

1) One Trigger Per Object
2) Logic-less Triggers
3) Context-Specific Handler Methods
4) Bulkify your Code
5) Avoid SOQL Queries or DML statements inside FOR Loops
6) Using Collections, Streamlining Queries, and Efficient For Loops
7) Querying Large Data Sets
8) Use @future Appropriately
9) Avoid Hardcoding IDs

Always remember below points before writing trigger :-
1) Order Of Execution
2) Recursive Trigger
3) Learn about Other Trigger Framework

Recording

Episode 5 will be presented by Purushottam Bhaigade on Feb 14, 2020 at 6 PM Indian Standard Time.

Assignment

Complete below assignment to win $1000 Salesforce Voucher. Click here for rule.

Create Custom object Invoice with field Total Amount
Create child object Invoice Line Item with Lookup relationship to Invoice.
Add price field into Invoice Line Item.
Write trigger on Invoice Line Item which will add some of all child records to parent Invoice

Trigger Handler Pattern

Further Learning

Trigger Framework

Don’t forget to register for our next session on Test Classes. Check this post for all other session detail.

Please note that we have limit of 500 attendees that can join the online sessions. However, recording will be posted on our YouTube channel. Make sure to subscribe our YouTube channel to get notification for video upload.

So, learn at your pace and free will and ace your journey to Salesforce!

13,120 total views, 60 views today

29 comments

  • Completed Assignment for Day 5
    I have created one trigger “InvoiceAmountUpdate” and one class “InvoiceAmountUpdateHandler”

  • Solution for Assignment : Trigger on Invoice Line Item which will add sum of all child records to parent Invoice:

    trigger AddInvoiceItems on Invoice_Line_Item__c ( after insert, after update, after delete ) {

    List ListIds = new List();

    if ( Trigger.isInsert || Trigger.isUpdate ) {

    for ( Invoice_Line_Item__c item : Trigger.New ) {
    if ( Trigger.isInsert || ( Trigger.isUpdate && Trigger.OldMap.get(item.ID).price__c!=item.price__c) ) {

    listIds.add(item.Invoice__c);

    }
    }
    }

    if(Trigger.isDelete)
    {
    for( Invoice_Line_Item__c item : Trigger.Old ) {

    listIds.add(item.Invoice__c);

    }
    }

    Map TotalPriceMap = new Map();

    for ( Invoice_Line_Item__c item : [ SELECT Id, price__c, invoice__c FROM Invoice_Line_Item__c WHERE invoice__c IN : ListIds ] ) {

    Decimal totalPrice = 0;
    if( TotalPriceMap.containsKey ( item.invoice__c ) )
    totalPrice = TotalPriceMap.get( item.invoice__c );
    totalPrice = totalPrice + item.price__c;
    TotalPriceMap.put(item.invoice__c,totalPrice);
    }

    List updateInvoice = new List();
    for ( Id invoiceId : TotalPriceMap.KeySet() ) {
    Invoice__c inv = new Invoice__c ( Id = invoiceId );
    inv.Total_Amount__c = TotalPriceMap.get( invoiceId );
    updateInvoice.add(inv);
    }

    if ( updateInvoice.size() > 0 )
    Update updateInvoice;

    }

    • HI bro, i have one question, you have declared empty map . since it is empty how you are searching using containskey

      • Thanks for pointing out. It should be like this:

        Map TotalPriceMap = new Map();

        I believe, datatype got missed while I pasted my solution.
        I am sorry about it. I will check and correct it.

        Thanks again!

  • HI bro, i have one question, you have declared empty map . since it is empty how you are searching using containskey

    • Facing some issue with code within angle brackets after I posted comment.

      Correction:
      List ListIds = new List(); // Id within angle brackets after List
      Map TotalPriceMap = new Map(); // Id,Decimal within angle brackets after Map
      List updateInvoice = new List(); // Invoice__c within angle brackets after List

  • Noticed some issues with posted code : I noticed code(data type) within angle brackets got removed after I posted it. I am sorry about this.
    Please add following datatype ( written after backslash ) within angle bracket after List or Map

    Correction:

    List ListIds = new List(); // Add Id within angle brackets after List

    Map TotalPriceMap = new Map(); // Add Id , Decimal within angle brackets after Map

    List updateInvoice = new List(); // Add Invoice__c within angle brackets after List

  • Code for Assignment Day 5
    ——————————–

    trigger InvoiceAmountUpdate on Invoice_Line_Item__c (after insert,
    after update,
    after delete) {

    String invoiceId = ”;
    if(Trigger.isInsert || Trigger.isUpdate) {
    for(Invoice_Line_Item__c invoiceLineItem : Trigger.new) {
    if(invoiceLineItem.Invoice__c != null) {
    invoiceId = invoiceLineItem.Invoice__c;
    }
    }
    }
    if(Trigger.isDelete){
    for(Invoice_Line_Item__c invoiceLineItem : Trigger.old) {
    if(invoiceLineItem.Invoice__c != null) {
    invoiceId = invoiceLineItem.Invoice__c;
    }
    }
    }
    if(invoiceId != ”) {
    InvoiceAmountUpdateHandler.updateInvoiceAmount(invoiceId);
    }
    }

    —————————————————————————–

    public class InvoiceAmountUpdateHandler {
    public static void updateInvoiceAmount(String invoiceId) {
    List items = new List();
    items = [select Id,price__c from Invoice_Line_Item__c where Invoice__c = :invoiceId];
    Decimal amount = 0;
    for(Invoice_Line_Item__c item : items) {
    amount = amount + item.Price__c;
    }
    Invoice__c invoice = new Invoice__c();
    invoice.Id = invoiceId;
    invoice.Total_Amount__c = amount;
    update invoice;

    }
    }

    • Hi! I have written a code for trigger assignment task and its working well for insert and update. Can you please tell me whether I need to modify my code for better results..

      Parent: Invoice__c
      Child: Invoice_Line_Item__c

      Trigger code:
      trigger Invoice_Line_Item__cTrigger on Invoice_Line_Item__c (after insert, after Update) {

      if((trigger.IsInsert == true && Trigger.Isafter == true) ||(trigger.IsUpdate == true && Trigger.Isafter == true)){

      Invoice_Line_ItemHandler.AmoutUpd(trigger.new);
      }
      }

      APEXHANDLER::

      public class Invoice_Line_ItemHandler {

      public static list P_id = new list();
      public static decimal amount=0;

      public static void AmoutUpd(list ChildRec){

      for(Student__c Pid : StuRec){

      if(pid.Teacher_name__c != null){

      P_id.add(pid.Invoice_name__c);
      }
      }
      list Rec = [SELECT Total_amout__c,name,(SELECT Invoice_name__c,price__c FROM Invoice_Line_Item__r) FROM Invoice__c WHERE ID IN :P_id];

      for(Invoice__c a: Rec){

      for(Invoice_Line_Item__c b: a.Invoice_Line_Item__r){

      amount = amount+ b.price__c ;
      }

      a.Total_amout__c = amount;
      }
      update Rec;
      }

      }

  • hello
    I copied the Handler Class from above into the Dev console but I receive Unexpected token ‘List’. error for this statement:
    List items = new List();

    What am i missing here?

    -jim

  • Logic for Trigger
    ================
    public class ApexHourTriggerAssignment {

    public static void updateInvoceObjectField(List lstinvln){
    Decimal amount=0;
    Set liStIds = new Set();
    for (Invoice_Line_Up__c ilu :lstinvln) {
    if(ilu.Invoice_Name__c != null) {
    liStIds.add(ilu.Invoice_Name__c);
    }
    }
    List ListInvoice = [Select id, Total_Amount__c, (select id, price__c from Invoices_Line_up__r)
    from Invoice__c Where Id IN :liStIds];
    ListListInv = new List();
    For(Invoice__c inv : ListInvoice){
    for(Invoice_Line_Up__c ilu1 : inv.Invoices_Line_up__r){
    amount = amount + ilu1.price__c;
    }
    inv.Total_Amount__c = amount;
    ListInv.add(inv);
    }
    update ListInv;
    }
    }

    ======================
    trigger ApexHourTriggerAssignmentTrigger on Invoice_Line_Up__c (After insert,After Update) {

    ApexHourTriggerAssignment.updateInvoceObjectField(Trigger.new);
    }

Leave a Reply