Blog Categories

Posted by on Nov 30, 2015 in Featured Blogs, Tutorials | 34 comments

10 Things To Know About Apex Triggers in Salesforce

10 Things To Know About Apex Triggers in Salesforce

  [Things2Know# 1]

What on earth these Apex Triggers mean?

Apex Trigger is an apex code that gets executed whenever a specific DML operation is performed on an Object record. It allow developers to programmatically check for duplicate records, update fields across objects, automate the creation of new records based on criteria, and much more.

[Things2Know# 2] 

When to Use Apex Triggers?

So this is a big question.Ideally,Apex Triggers are used when the requirement is not fulfilled by declarative operations such as workflow,process builder etc.As a best practice always look for declarative approach , But most of the developers who are not aware of the declarative approaches always go for triggers.

As a practice go for wokflows/flows first and  then the process builder(this is a new but an awesome feature which has brought renaissance to the world of Salesforce Development).I love the series-Learning Process Builder  by Rakesh Gupta which has many scenarios explaining how process builder works.

 

[Things2Know# 3] 

Know about the  basic syntax of a Trigger:

 

/*
<triggername> name of the trigger you want 
<Object> name of object,custom or standard,whatever it can be
<DML Events> insert,update etc..explained later in blog
*/
trigger < triggername > on < Object >( DML Events )

{

      /* — You need to write all your crappy code for your 
          Logic Here  — */

}

[Things2Know# 4] 

Here are  examples for Apex Trigger which explains a lot!!

So this is main part of this blog you were waiting for,here I bring 2 examples which will help you to understand much more.Try these codes and let me know in comments part if you face any issue implementing them

Example 1

/************************************************************************************
 * Trigger Name:AccountTriggerForUpdateContacts
 * Purpose:performing different operations on account and realted contacts based on the scenario
 * Note:Please make sure you have custom field-Account_Number_1__c on your Contact Object 
 * *********************************************************************************/

trigger AccountTriggerForUpdateContacts on Account (before insert,before update,after insert,
                                                    after update,before delete) 
{
	//Create a map of List of contacts and Account Ids
    MAP<Id,List<Contact>>MapAccountIdToListOfContacts=new MAP<Id,List<Contact>>();    
	for(contact objcontact:[select Id,AccountID,Account_Number_1__c from contact where
                           AccountId IN:Trigger.newmap.keyset()])
    {
        //populate map here for Account Id and List of Contacts associated with it 
        //which will be used later in code
        if(MapAccountIdToListOfContacts.containsKey(objcontact.AccountId)) 
        {
            List<contact>lstcontact = MapAccountIdToListOfContacts.get(objcontact.AccountId);
            lstcontact.add(objcontact);
            MapAccountIdToListOfContacts.put(objcontact.AccountId, lstcontact);
		} 
        else 
        {
			MapAccountIdToListOfContacts.put(objcontact.AccountId, new List<contact> { objcontact});
		}
    }
    //Praparing a List to insert contacts
    List<contact>lstcontactToInsert=new List<contact>();
    //Preparing a  List of Contact to Update
    List<contact>lstcontactToUpdate=new List<contact>();
    for(Account objAccount:Trigger.New)
    {
        //Scenario 1:If a new Account is created and the account number is not blank 
        //Create a contact with last name chaturvedi and contacts's 
		//account number similar to account number
        if(Trigger.isinsert && (objAccount.accountnumber!=NULL || objAccount.accountnumber!=''))
        {            
            //create a contact with account number same to account's account number
            contact objcontact=new contact();
            objcontact.lastname='chaturvedi'; 
			//Since this is mandatory field on contact,I need to put this down
            objcontact.Account_Number_1__c=objAccount.accountnumber;
            //Adding this contact to list to make it bulkified
            lstcontactToInsert.add(objcontact);
            
        }
        //Update the Account number of all the contacts asscoiated with that Account
        if(Trigger.isupdate)
        {            
            if(objAccount.accountnumber!=Trigger.oldMap.get(objAccount.Id).accountnumber)
            {
                for(contact objcont:MapAccountIdToListOfContacts.get(objAccount.Id))
                {
                    objcont.account_number_1__c=objAccount.accountnumber;
                    //Adding this contact to list to make it bulkified
                    lstcontactToUpdate.add(objcont);
                }
            }
        }
        
    }
    //Insert the contact list 
    if(lstcontactToInsert.size()>0)
        insert lstcontactToInsert;
    
    //Update contact List 
    if(lstcontactToUpdate.size()>0)
        update lstcontactToUpdate;
}

Example 2

/************************Name : UpdateContactFieldsTrigger************************/
/***********************************PURPOSE***************************************
 *     Whenever a new record  of opportunity is created and the amount field 
 *              in the Opportunity object has some value then-
 *        new record against a contact selected should be created with the 
 *  'last gift amount field in contact object' equal to 'opportunity Amount Field'
 *********************************************************************************/
/************************************NOTE*****************************************
 *  For this trigger first create a new custom field on contact object with 
 *    Name:(Last Gift Amount) and API Name:(External_Last_Gift_Amount__c) 
 *       Also Create a Lookup field on Opportunity with Contact
 *********************************************************************************/

Trigger UpdateContactFieldsTrigger on Opportunity(After Insert,After Update)
{
    //Set of Contact Id
    SET<Id>ContactSet = new SET<ID>();
    for(Opportunity NewOpp : [Select ID, Contact__c From Opportunity 
                              where ID In:Trigger.Newmap.Keyset()])
    {    
    //Adding a perticular Contact selected from lookup while creating 
	//opportunity record to Set of Contact ID
        ContactSet.add(NewOpp.Contact__c);                            
    }
    //Now Creating a Map of Contact IDs for a perticular contact 
	//specifying The condition that it should be present in the Set of Contact in Previous Step
    MAP<Id,Contact>MapIdToContacts = new MAP<Id,Contact>
									([select id, External_Last_Gift_Amount__c 
                                     from contact where id IN : ContactSet]);
    //List to Hold Contacts related to an opportunity record                                                       
    List<contact> ListContact = new List<contact>();
    For(Opportunity NewOpp : [Select ID, Amount, Contact__c From Opportunity 
                              where ID In : Trigger.Newmap.Keyset()])
    {
        If(NewOpp.Amount !=0 || NewOpp.Amount != Null )
        {
            MapIdToContacts.get(NewOpp.Contact__c).External_Last_Gift_Amount__c = NewOpp.Amount;
            ListContact.add(MapIdToContacts.get(NewOpp.Contact__c));
        }
    }
    //Finally updating contact List and the field 'Last Gift Amount'
	//also gets updated
    update ListContact;
}

 

[Things2Know# 5] 

Are you Confused-Before v/s After Triggers?

Triggers can be primarily classified into two types:

  • Before trigger
  • After trigger

Before Triggers:  Before triggers are ones that get executed before the record is saved to the database.

After Triggers: After triggers are ones that get executed after the record is saved to the database.

Most of the Triggers we use are Before Triggers.You may be wondering why so many triggers are before triggers. There’s a good reason – they’re simpler to use. If you need to make any changes to a record entering your after trigger, you have to do a DML statement. This isn’t necessary in a before trigger – changes to records entering your trigger always save!

Here is the usages as well:

Usage of Before Triggers:

  • Can be used to perform validations and stop the creation / updation / deletion of records if they are not satisfying the criteria.
  • Data can be modified in before triggers only, hence record field auto population by the system can be performed here.

Usage of After Triggers:

  • By the time these triggers execute the record ID and the system generated fields such as created by, modified by etc… are generated by the system and these fields such as ID can be used to build relationships i.e create relationship records.

[Things2Know# 6] 

Deep Dive in  DML events for  triggers

  • Before InsertTrigger that executes due to an insert operation and before the record is saved to the database it is a before Insert trigger
  • Before UpdateTrigger that executes due to an update operation and before the record is saved to the database it is a before update trigger
  • Before Delete Trigger that executes due to a delete operation and before the record is saved to the database it is a before delete trigger
  • After Insert :Trigger that executes due to an insert operation but after the record is saved to the database it is an after Insert trigger
  • After UpdateTrigger that executes due to an update operation and after the record is saved to the database it is an after update trigger
  • After DeleteTrigger that executes due to a delete operation and after the record is deleted from the database it is an after delete trigger
  • After UndeleteTrigger that executes due to a undelete operation and after the record is undeleted from the database it is an after undelete trigger

[Things2Know# 7] 

Let’s look at Context Variables available  for Apex Triggers

 

   Variable  

               Usage

 

isExecuting Returns true if the current context for the Apex code is a trigger, not a Visualforce page, a Web service, or an execute anonymous() 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 theAPI.)

 

new Returns a list of the new versions of the sObject records.

Note that this sObject list is only available in insert and update triggers, and the records can only be modified in before triggers.

 

newMap A map of IDs to the new versions of the sObject records.

Note that this map is only available in before update, after insert, and after update triggers.

 

Old Returns a list of the old versions of the sObject records.

Note that this sObject list is only available in update and delete triggers.

 

oldMap A map of IDs to the old versions of the sObject records.

Note that this map is only available in update and delete triggers.

 

Size  

The total number of records in a trigger invocation, both old and new.

 

 

[Things2Know# 8] 

What to consider for Context Variables?

Be aware of the following considerations for trigger context variables:

  • Trigger.new and Trigger.old cannot be used in Apex DML operations.
  • You can use an object to change its own field values using trigger.new, but only in before triggers. In all after triggers, trigger.new is not saved, so a runtime exception is thrown.
  • Old is always read-only.
  • You cannot delete trigger.new.

You can learn more about Context Variables here

[Things2Know# 9] 

Do you know Where comes the Triggers in Salesforce order of execution ?

  • Old record loaded from database (or initialized for new inserts)
  • New record values overwrite old values
  • System Validation Rules
  • All Apex “before” triggers
  • Custom Validation Rules
  • Record saved to database (but not committed)
  • Record reloaded from database
  • All Apex “after” triggers
  • Assignment rules
  • Auto-response rules
  • Workflow rules
  • Escalation rules
  • Parent Rollup Summary Formula value updated (if present)
  • Database commit
  • Post-commit logic (sending email)

You can check more about order of execution

[Things2Know# 10] 

 What else you can try out  after this blog?

I would love to hear feedback in comments.Thanks for Reading.