Salesforce apex triggers with practice examples

What are triggers in apex

The salesforce apex trigger is a piece of code executed when a database event occurs in Salesforce. Developers write an apex trigger to customize system behavior in order to fulfilling business requirements when records are inserted, updated, or deleted in the Salesforce org.

What are the different types of triggers

1. Before triggers

These triggers execute before records are saved to the database. They are useful for updating field values and running validation rules on the record that initiated the DML operations.

2. After triggers

These triggers execute after records are saved to the database. They are useful for tasks such as creating or updating related records and sending emails. The fields set by system such as record ids, created/last modified date are accessible in the after triggers. But the records in the trigger context cannot be updated after triggers.

What are trigger events

Trigger events are specific database operations that happen in the system. Apex provides built-in variables that enable developers to customize code execution when specific database events occur. Triggers can run either before or after the following database events.

Following are the trigger events in apex.

  • Before insert

    Fires before records are inserted into the database

    After insert

    Fires after records are inserted into the database
  • Before update

    Fires before records are updated and saved to database

    After update

    Fires after records are updated and saved to the database.
  • Before delete

    Fires before records are deleted from database

    After delete

    Fires after records are deleted from database

What are trigger context variables

Trigger context variable lets developers get contextual information about the current trigger execution. This is useful when running business rules for specific conditions. Following are the trigger context variables provided by salesforce.

VariableUsage

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.

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.

How to write an apex trigger

Apex triggers can be created from setup menu or the developer console or through visual studio code. As a developer, practicing creation via visual studio code offers several advantages.

The basic syntax for writing an apex trigger on account for before insert is given below.

Trigger accountTrigger on Account(before insert){
    
    //Before event handler
    if(Trigger.isBefore){
        
        //Before insert event handler
        if(Trigger.isInsert){

        }
    }
}

Note: Trigger.isBefore, Trigger.isInsert are the trigger context variables.

How to enable/disable apex triggers

Apex triggers can be enabled or disabled by toggling the active flag on the trigger. The way you do this depends on whether you're working in a production environment or in a sandbox environment.

To disable an apex trigger from a sandbox

Go to set up -> apex triggers -> and select your specific trigger and uncheck the active flag.

Enable/disable apex trigger

To disable an apex trigger from production

Disabling a trigger in a production organization requires a deployment, and there are few ways to achieve this task.

1. Deploy using changesets

  • Disable the trigger from sandbox.
  • Create a changeset including the disabled trigger and test classes.
  • Upload the changeset to production organization and deploy it.

2. Deploy using metadata

  • Disable the trigger from the metadata file your-triggername.trigger-meta.xml by setting the status element to Inactive.
  • Deploy the metadata file using ANT/Workbench/CICD tool to your production organization.

How to bulkify triggers

The database operations in Salesforce can handle either individual records or thousands of records simultaneously. Salesforce automatically divides incoming records into chunks of up to 200 records. Failing to bulkify the trigger code can quickly lead to reaching governor limits. Therefore, optimizing the trigger code for bulk record operations is crucial.

In order to bulkify resource intensive operations, use apex collections such as list, set and maps.

Here is a sample trigger

1. Query parent case records in trigger - Not bulkified

public class caseTriggerHandler{

    public static void beforeInsert(){
        List<Case> newCases = Trigger.new;
        for(Case caseRec : newCases){
            //Find the parent case ids from current case record
            Case parentCase = [Select id, caseNumber from Case where id =:caseRec.parentId limit 1];
        }
    }
}

2. Query parent case records in trigger - Bulkified

public class caseTriggerHandler{
            
    public static void beforeInsert(){
        List<Case> newCases = Trigger.new;
        List<Id> parentIds = new List<Id>();
        Map<Id,Case> mapIdParentCase = new Map<Id,Case>();
        
        //Find all parent case id's
        for(Case caseRec : newCases){
            parentIds.add(caseRec.parentId);
        }
        
        //Query all parent cases in one single query and use map to store them
        for(Case caseRec : [Select id,caseNumber from Case where id IN :parentIds]){
            mapIdParentCase.put(caseRec.id, caseRec);
        }

        for(Case caseRec : newCases){
            //Find the parent case ids from current case record -  no query inside for loop
            Case parentCase;
            if(mapIdParentCase.containsKey(caseRec.Id)){
                parentCase = mapIdParentCase.get(caseRec.Id)
            }
        }
    }
}

Salesforce apex trigger practice examples

If you're looking to become an expert in Salesforce custom development, practicing writing efficient triggers is very critical. We've set up a number of scenarios where you can practice writing your own Apex code. Additionally, we have set up test cases to ensure that the code is working as expected and following Salesforce best practices. Following are a few sample scenarios.

1. Before Insert Trigger

Apex trigger to automatically populate the company field on leads

Company name on lead is a required field and inserting leads without company will cause the DML operation to fail. Solve the before insert apex trigger event to add a company name if the given lead doesn't have a company name populated.

Solve this practice example

2. After Insert Trigger

Apex trigger to log tasks automatically when a case is created

A company requires to automatically log a task when an inbound case is created with origin as phone.

Solve this practice example

How to avoid recursion in apex triggers

Sometimes, business scenarios result in updating records in the same object within trigger contexts, which ends up running the same trigger that initiated the transaction. This will likely cause recursion if not handled correctly.

To avoid recursion in Apex triggers, identify the business logic that is likely to run again and isolate it with a static variable. Static variables retain their values between trigger contexts. Default the value of the static variable to false and execute your specific code only if the value is false. Once the code is executed, set it to true so that it will not rerun the next time.

Trigger order of execution

In Salesforce, the order of execution outlines how different tasks unfold when saving or updating a record. It's important for developers to know this sequence to organize the execution of business logic when customizing an apex triggers.

The following is the execution flow of Apex triggers

apex trigger order of execution