How to Write your first Salesforce Apex Trigger

Writing Apex triggers enable you to do custom actions before or after changes to Salesforce records, such as insertions, updates, or deletions. A  trigger is an Apex script that executed before or after specific data manipulation language (DML) events occur (such as before object records are added to the database, or after records are deleted). In additiontriggers help you do custom actions before or after changes to Salesforce records.

The trigger is Apex code that executed before or after the following types of operations:

  • Insert
  • Update
  • Delete
  • Merge
  • Upsert
  • Undelete

For example, you can have a trigger run before an object's records in a couple of scenarios. When records are being inserted into the database after records have been deleted, or even after a record is being restored from the Recycle Bin.

There Are Two Types Of Triggers:
  • Before triggers: It is used to update or authenticate record values before it is saved in the database.
  • After triggers: It is used to access values of the record that are stored in the database and use this value to make changes with other records. After trigger records are read-only.
Trigger trigger Name on sObject(Trigger event)
{
//logic
}
Bulk Triggers

All triggers are bulk triggers by default and can process multiple records at a time. Therefore, I believe you should always plan on processing more than one record at a time.  Also, Bulk triggers can handle both single record updates and bulk operations like:

  • Data import
  • com Bulk API calls
  • Mass actions, such as record owner changes and deletes
  • Recursive Apex methods and triggers that invoke bulk DML statements

Trigger Context Variables

Apex triggers define implicit variables that allow developers to access run-time context. These variables are contained in the System.Trigger class.

Actions of Different Trigger Events

The following are lists of considerations about actions of different trigger events:

Trigger Event Change fields using trigger.new Update original object using an update DML operation Delete original object using a delete DML operation
beforeinsert Allowed. Not applicable. Not applicable.
afterinsert Not allowed. A runtime error is thrown, as trigger.new is already saved. Allowed. Allowed, but unnecessary. The object is deleted immediately after being inserted.
beforeupdate Allowed. Not allowed. A runtime error is thrown. Not allowed. A runtime error is thrown.
afterupdate Not allowed. A runtime error is thrown, as trigger.new is already saved. Allowed. Allowed.
beforedelete Not allowed. A runtime error is thrown. trigger.new is not available before delete triggers. Allowed. Not allowed.
afterdelete Not allowed. A runtime error is thrown. trigger.new is not available after delete triggers. Not applicable. The object has already been deleted. Not applicable. The object has already been deleted.
afterundelete Not allowed. A runtime error is thrown. trigger.old is not available after undelete triggers. Allowed. Allowed, but unnecessary. The object is deleted immediately after being inserted.
Before Insert Trigger
  • In this case, the trigger will be fried when a new record will be saved in the database.
  • In before insert, trigger. New stores a new list of records that will be inserted.
Example
Name duplication trigger on Contact (before insert, before update)
//this is the logic
{
   Set<String> lastName = new Set<String>();
   Set<String> setname = new Set<String>();
   for(Contact cont : Trigger.new)
   {
          lastName.add(cont.email);
   }

   for(Contact cont : [SELECT lastName FROM Contact WHERE email in : lastName])
   {
          setname.add(con.lastName);
   }

   if(Trigger.isInsert || Trigger.isUpdate)
     for(Contact a:trigger.new)
     {
         if(setname.contains(a.lastName))
        {
                 a.lastName.adderror('This email already exists');
        }
     }
}
After Insert
  • This trigger will fire, after a new record is inserted successfully in the database.
  • New is going to hold a new record inserted into the database.
  • After insert trigger is read-only operation. We can do DML operations on new records inserted into the database.
Example
After Insert trigger on Account (after insert)
//this is the logic
{
for(Account acc: Trigger.new)
{
   Account oldAcc = Trigger.oldMap.get(acc.Id);
    if(oldAcc.phone != acc.Phone)
    {
      List<Contact> contList = [SELECT Id, AccountId, Phone FROM  Contact where AccountId = :acc.Id];
      List<Contact> newids = new List<Contact>();
      for(Contact con: contList)
      {
       if(con.Phone != acc.Phone)
       {
         con.Phone = acc.Phone;
         newids.add(con);
       }
      }
      if (!newids.isEmpty())
      {
        update newids;
      }
    }
}
}
Update Trigger Events

There are two types of update events, that we are going to explain in detail:

  • Before update
  • After Update

Trigger. Old and Trigger. New are update events in Salesforce.

Before Update
  • New: Trigger. New is going to hold the list of records which going to be updated.
  • Old: Trigger. Old is going to hold the set of old values that will be updated.

It’s going to store the set record before updating it to the database.

Example
Before Update Trigger on Contact (before update)
//this is the logic
{
List<Account> acclist = new List<Account>();
for(Contact acc:trigger.old)
{
  Account a = new Account();
  c.Name=acc.Lastname;
  c.Phone=acc.Phone;
  acclist.add(a);
}
insert acclist;
}
After Update
  • The trigger will fire, only when the changes are made in the database.
  • In the after update trigger operation we can only read the data from the trigger.
  • If we want to make any changes, we need to perform DML operation.
Example
After Update trigger Contact on Account (after update)
//this is the logic
{
if(trigger.IsAfter && trigger.IsUpdate)
{
  Set<Id> ids = new Set<Id>();
  List<Contact> contlist = new List<Contact>();
  for(account a:trigger.new)
  {
    ids.add(a.id);
    List<Contact> cont =[SELECT Id,Phone,LastName,Account.Phone FROM Contact WHERE AccountId in:ids];
    for(Contact c:cont)
    {
      c.Phone = c.Account.Phone;
      contlist.add(c);
    }
    update contlist;
  }
}
}
Delete Event 

There are two types of delete events, that we are going to explain:

  • Before Delete
  • After Delete
Before Delete (Trigger. Old)

The Trigger.Old will be holding the records that will be deleted. These records are read-only by the operation.

Example
Before Delete Trigger that deletes Account on Account (before delete)
//this is the logic
{
for(Account Acc:trigger.old)
{
  acc.Name.addError('Account cannot be deleted');
}
}
After Undelete ( Trigger.newMap and Trigger.oldMap )
  • When we are undeleting records from the recycle bin after undeleting operation required.
  • New is going to store the record which is undeleting from the recycle bin.
Trigger.oldMap

Trigger.oldMap is a map of IDs to the old version of the sObject records.

Note
Note that this map is only available in update and delete triggers.
Example
Trigger Map on Account (before update)
//this is the logic
{
  Map<Id,Account> accMap = new Map<Id,Account>();
  accMap = trigger.oldMap;
  for(Account acc : trigger.new)
  {
    Account oldvalue = new Account();
    oldvalue = accMap.get(acc.Id);
    if(acc.Phone != oldvalue.Phone)
    {
      acc.Phone.addError('Phone cannot be changed');
    }
  }
}
Trigger.newMap

Trigger.newMap is a map of IDs to the new version of the sObject records.

Note
This map is only available before update, after insert, and after update triggers.
Example
Trigger update Phone Contact on Account (before update)
//this is the logic
{
  if(trigger.isbefore && trigger.isupdate)
  {
    Map<Id,Account> mapcon= trigger.newmap;
    List<Contact> cont = new List<Contact>();
    List<Contact> con = [SELECT Id,Phone,AccountId FROM Contact WHERE AccountId in : mapcon.keyset()];
    for(Contact c : con)
    {
      c.Phone = mapcon.get(c.AccountId).Phone;
      cont.add(c);
    }
    update cont;
   }
}
Summary

Apex triggers can help you to perform customized operations in the Salesforce database.

Want to learn more?

Read more about How to Write Good Requirements
Check out this Trail: Get Started With Apex Triggers

 

Share this article...

Salesforce Mentor, with 10 years Salesforce experience, Hardcore Admin & Guru Developer, Geek, Animal lover, and dog & cat rescuer activist. Lifetime student, Stand-Up comedian wannabe, Photographer, Gamer, Anime lover, and coffee addict. Spreading Salesforce love and teaching beyond my capacity. Aiming to become Tech Architect!

One Ping

  1. Pingback: How to define and initialize a Map, List, and Set with Apex |

2 Comments

  1. software development Reply

    Accidentally, I found this post and I can say , it was
    quite interesting. I enjoyed the perspective and
    their research efforts, but it wasn’t anything revolutionary.
    In summary, a decent attempt.

    1. Darko Todorovski Post author Reply

      Thank you for sharing your thoughts on the post you stumbled upon. While it may not have been a groundbreaking revelation, it’s still great to hear that you found the perspective and research efforts to be interesting. Sometimes, even small attempts can lead to significant progress and growth. It’s always refreshing to see individuals making an effort to contribute to their field or community, and I hope this post inspires others to do the same.

Leave a Reply

Your email address will not be published. Required fields are marked *