salesforce data migration services

10 Things To Know About Apex Triggers In Salesforce

In this blog, I have summarized the 10 Things To Know About Apex Triggers in Salesforce I believe you should know as a beginner when you write apex code.

1. What on earth these Apex Triggers mean?

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

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 looks for a declarative approach, But most of the developers who are not aware of the declarative approaches always go for triggers.

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

3.Know about the  basic syntax of a Trigger:

[php]

/*
<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  — */

}

[/php]

4.Apex Trigger Examples

So this is the 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

[php]
/************************************************************************************
* 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;
}

[/php]

Example 2

[php]

/************************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;
}

[/php]

5. Are you Confused-Before v/s After Apex 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 you are after the trigger, you have to do a DML statement. This isn’t necessary for a before trigger – changes to records entering your trigger always save!

Here are the usages as well:

Usage of Before Apex Triggers:

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

Usage of After Apex 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.

6.Deep Dive in  DML events for  Apex 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 DeleteTrigger 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

7.Context Variables  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.

 

8. Context Variables Considerations

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 the 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

9. Do you know where appears the Apex Triggers in the 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 the database (but not committed)
  • Record reloaded from the 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 the order of execution

10. What else you can try out after this blog?

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