Tag Archives: Apex Trigger

Salesforce Trigger Handler Patterns

To move all code from Trigger to Apex Classes(Handler Classes) is one of the Salesforce Best Practices. Here is an example to write Trigger Handler class.

Apex Trigger:

trigger objectTrigger on Object (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    
    objectTriggerHandler handler = new objectTriggerHandler();
    
    //Before Insert
    if(Trigger.isInsert && Trigger.isBefore){
        handler.OnBeforeInsert(Trigger.new);
    }
    //After Insert
    else if(Trigger.isInsert && Trigger.isAfter){
        handler.OnAfterInsert(Trigger.new);
    }
    //Before Update
    else if(Trigger.isUpdate && Trigger.isBefore){
        handler.OnBeforeUpdate(Trigger.old, Trigger.new, Trigger.newMap);
    }
    //After Update
    else if(Trigger.isUpdate && Trigger.isAfter){
        handler.OnAfterUpdate(Trigger.old, Trigger.new, Trigger.newMap);
    }
    //Before Delete
    else if(Trigger.isDelete && Trigger.isBefore){
        handler.OnBeforeDelete(Trigger.old, Trigger.oldMap);
    }
    //After Delete
    else if(Trigger.isDelete && Trigger.isAfter){
        handler.OnAfterDelete(Trigger.old, Trigger.oldMap);
    }
    //After Undelete
    else if(Trigger.isUnDelete){
        handler.OnUndelete(Trigger.new);
    }
}

Trigger Handler Apex Class:

public with sharing class ObjectTriggerHandler {
    
    private boolean isExecuting = false;
    
    public ObjectTriggerHandler(boolean isExecuting){
        this.isExecuting = isExecuting;
    }
    
    public void OnBeforeInsert(List<Object> newObjects){
        //EXECUTE BEFORE INSERT LOGIC
    }
    
    public void OnAfterInsert(List<Object> newObjects){
        //EXECUTE AFTER INSERT LOGIC
    }
    
    public void OnBeforeUpdate(List<Object> oldObjects, List<Object> updatedObjects, Map<Id, Object> ObjectMap){
        //BEFORE UPDATE LOGIC
    }
    
    public void OnAfterUpdate(List<Object> oldObjects, List<Object> updatedObjects, Map<Id, Object> ObjectMap){
        //AFTER UPDATE LOGIC
    }
    
    public void OnBeforeDelete(List<Object> ObjectsToDelete, Map<Id, Object> ObjectMap){
        //BEFORE DELETE LOGIC
    }
    
    public void OnAfterDelete(List<Object> deletedObjects, Map<Id, Object> ObjectMap){
        //AFTER DELETE LOGIC
    }
    
    public void OnUndelete(List<Object> restoredObjects){
        //AFTER UNDELETE LOGIC
    }
    
    public boolean IsTriggerContext{
        get{ return isExecuting;}
    }
}

Different Ways of Making a Field Mandatory in Salesforce

There are 4 ways of making the field mandatory:

Page Layout: Field can be made mandatory from the page layout when it needs to be made mandatory for a set of users.
Field Level Security: Field can be made mandatory from the FLS when it needs to be made mandatory for all the users in the Organization and even from the API’s.
Validation Rule: Field can be made mandatory from the Validation Rule, when it needs to be made mandatory for user who is using the same Page layout used by other users.
Before Triggers: we can also make a field mandatory using before trigger

Note: Salesforce.com recommends using the Page Layout option for making the field mandatory.

Avoid Duplicate Record Using Apex Trigger

Here in below example the trigger is on “Account” object, to check duplicate Account Names.

Apex Trigger:

trigger accountDuplicateCheck on Account (before Insert, before Update) {
    
    Map<String, Account> accMap = new Map<String, Account>();
    
    for (Account acc : System.Trigger.new) {
        
        //Make sure we don't treat account Name that isn't changing during an update as a duplicate.  
        if (System.Trigger.isInsert || (acc.Name != System.Trigger.oldMap.get(acc.Id).Name)) {
            
            //Make sure another new account isn't also a duplicate  
            if (accMap.containsKey(acc.Name)) {
                acc.Name.addError('Another account has the ' + acc.Name + ' same name.');
            } else {
                accMap.put(acc.Name, acc);
            }
        }
    }
    
    //Query to find all the Accounts in the database that have the same name as any of the Accounts being inserted or updated.  
    for (Account acc : [SELECT Name FROM Account
                        WHERE Name IN :accMap.KeySet()]) {
                            Account newAcc = accMap.get(acc.Name);
                            newAcc.Name.addError('An account with this name ' + acc.Name + ' already exists.');
                        }
}

Invoke Apex Class from Trigger

You can create static or instance methods on your Apex Class. In your trigger you can then have code that calls these classes. This is very similar to the way method calling works in other languages. Here is a simple example.

Apex Class:

public class SampleClass
{
    public void SampleMethod(List<Account> listAccount, Map<Id, Account> mapAccount){
        
    }
}

Apex Trigger:

trigger SampleAccount on Account (before insert) 
{
    for(Account a : trigger.New){
        SampleClass obj = new SampleClass(Trigger.New, Trigger.NewMap);
        obj.SampleMethod();
    }
}

Field Update in Salesforce Using Apex Trigger

Here in below example I’m updating a custom field “Comment__c” on Account object, based on the Annual Revenue field, using apex trigger.

Sample Code:

trigger AccountTrigger on Account(before Insert, before update){  
    for(Account acc : Trigger.new)   {       
        if(acc.AnnualRevenue > 500000000){       
            acc.Comments__c = 'Highly revenue customer';     
        }            
    }   
}