Salesforce coding lessons for the 99%
Finally, Apex tutorials for point-and-click admins! Written by a self-taught Google engineer.
  • Beginner Tutorials
    • Apex
    • Certifications
    • Career Info
    • Technical Architect
    • Visualforce
    • Videos
  • Apex Academy
  • Success Stories
  • About Me
  • Misc
    • Mailbag
    • Challenges
    • Links
    • Login to my Org
Follow @dvdkliuor SUBSCRIBE!

An extended look: How to write an Apex trigger

May 12, 2013

Preface: this post is part of the Write Your First Trigger From Start to Finish series.

Want to get a deeper understanding of our simple apex trigger? Look no further!

Here’s a reminder of the code we wrote in the original post:

trigger ForceForecasting on User (before insert) {
for (User userInLoop : Trigger.new) {
userInLoop.ForecastEnabled = true;
}
}

Let’s take a look at the most important line first. I gave this line a deep green background so you’d know it’s critical!

userInLoop.ForecastEnabled = true;

You can take away nothing else from this post, but just know that this is where all the magic happens. If you wanted to auto-populate the “Company” field on every new user instead, you could change this line to:

userInLoop.CompanyName = 'Google, Inc.';

…while leaving every other line of code the same and it would work!

Let’s move on to the next most important lines of code. This is our loop:

for (User userInLoop : Trigger.new) {
...
}

If this code was translated to normal talk, it would say “For every user in our trigger, do everything inside the brackets { }”. Every Salesforce trigger will always have one of these loops.

Finally, let’s talk about the boilerplate code. You can skip this if you want to save brain power.

trigger ForceForecasting on User (before insert) {
    ...
}

Every trigger in Salesforce has this boring code wrapped around it. All it does is “start” and “end” the trigger.

Glossary of Variables Used

trigger – Every trigger must begin with this!

ForceForecasting – this is the name we gave our trigger. We could’ve named it anything we wanted to!

User – This is the name of the standard sObject in Salesforce. Having this in the first line of code tells our trigger to operate on changes to this object. We can use custom objects too… Salesforce is so awesome!!!

before insert – This tells the trigger to fire before the User is inserted/created. We could’ve said before update if we wanted to as well. See a full list of operations here.

userInLoop – this is the variable we created to represent each specific user in the loop as it iterates one by one across all users in Trigger.new. This variable only exists inside the brackets of the loop! We could’ve made it edit any field on the User object by adding another field API name after the period instead. It’s good manners in the programming world to write variables names in camelCase.

Trigger.new – the special Salesforce variable that is a list of every User captured in our trigger. There will always only be one User unless you’re doing a bulk insert… like through Data Loader!

Next post: Example: How to write a test class!

48 Comments
Kevin DuPont
February 4, 2020 @ 4:14 pm

David…just recently sent you an e-mail..actually found your site afterwards…coming together more clearly now thanks.

Reply
Catherine
December 16, 2019 @ 2:31 pm

I just wrote my first Apex trigger – the first of many more! Thank you, David.

Reply
    David Liu
    December 16, 2019 @ 3:30 pm

    Proud of you Catherine!!!!

    Reply
Bryce Russell
July 10, 2019 @ 7:59 pm

I’m just getting started on your site, but you’ve already presented the information in a manner FAR more understandable than the Apex Developer Guide!

I’m committing to get my Dev 1 cert this year, and I can already tell I’ll be doing most of my studying here. Thank you so much for putting this together in a way that can be understood by people who aren’t already fluent in Java and C#!

-Bryce

Reply
    David Liu
    July 15, 2019 @ 9:21 pm

    Thank you Bryce!!

    Reply
Pieter
June 17, 2019 @ 6:05 am

Hey David, just wanted to share this: YES, success!
Just did my homework week #2 and created a functional trigger that changed the email of my newly created user.

Great feeling, thanks man!

Reply
Chanti
December 22, 2017 @ 6:16 am

Hi David,

Good Evening!

I have written above code with “before update” instead of before insert operation and used Trigger.Old inside For loop instead of New.

But its giving error for “old” where as working for “new”

Why cant we use Old in before update as we are updating existing record only.

Please help me understand the difference.

Thanks,
Chanti

Reply
abhishek
September 5, 2016 @ 6:42 am

Hey I love your tutorials

But can you pls tell me that how to make an online mcq test . Can it be made with help of visualforce only ?
I am student and I have got a project to make the online test .
Waiting for your reply pls

Reply
    David Liu
    September 6, 2016 @ 8:43 pm

    Check out surveyforce which does this – you can see all the code inside it once you download it!

    Reply
Mazlow Cohen
August 8, 2016 @ 11:49 am

Hi David,

I was wondering how I could write a for loop instead of a for each loop to cycle through each object in the trigger. The reason being, I want to reference the number that object is in the List of objects in the trigger- later in the code after cycling through the loop. I have tried google searches and all the triggers seem to use this format- for each loop. I also posted on developer forum, but haven’t heard back and I wanted your opinion on this.

“for (User userInLoop : Trigger.new) {…}”

I tried using a for loop like this for account trigger- “for(Integer i = 0; i < Trigger.new.size(); i++) {

Account a = Trigger.new.get(i);

//do some code on Account a…

}

//later i need to reference i(the number the object is in the Trigger

"

I also tried this, which didn't work-

List Accs = Trigger.new();

for(Integer i = 0; i < Accs.size(); i++) {

Account a = Accs.get(i);

//do some code on Account a…

}

These both kept giving me an error. Is this not allowed?

Thanks!
Mazlow

Reply
    Mazlow Cohen
    August 8, 2016 @ 1:21 pm

    Hi David,

    Someone on dev forums replied with answer that worked. Here was the solution: Thanks, Mazlow

    list lstAccount = Trigger.new;
    for(Integer i = 0; i < Trigger.new.size(); i++)
    {

    Account a = lstAccount[i];

    }

    Reply
      David Liu
      August 8, 2016 @ 3:57 pm

      That’s it =)

      Another thing you can do is create an Integer variable outside the trigger, then increment it inside.

      Reply
        Mazlow
        August 8, 2016 @ 4:45 pm

        Wow! Great idea Thanks!

        Reply
piyush
March 31, 2016 @ 5:51 am

hello David ..please enplane uses of Trigger.New

Reply
Sam
March 29, 2016 @ 4:26 am

Hi David,

I have copied and pasted your ForceForcasting trigger above into my practice org exactly, also I’ve created my own in the same format with the aim of populating the company name field.

Issue is I am having no luck when creating a new user (both triggers are before insert). Neither the Allow Forecasting is being ticked or Company Name fields is being populated – any idea what could be up?

Thanks for the tutorials by the way, keep it up!

Sam

Reply
    Anonymous
    May 11, 2016 @ 7:47 pm

    Use the salesforce license to create an user. it worked for me

    Reply
Sundar prithvi
November 19, 2014 @ 3:52 am

Hi,

Cant we update the picklist values for the standard object say Locale to somehthing with this code.

Reply
    Sundar prithvi
    November 19, 2014 @ 4:30 am

    Found it in the next section in Apex class,for LocaleSidKey = ‘en_US’

    Where can we see for the avaliable picktlist values for LocaleSidKey .

    Reply
      David Liu
      November 19, 2014 @ 7:48 pm

      Check this page out!
      https://help.salesforce.com/apex/HTViewHelpDoc?id=admin_supported_locales.htm

      Sundar is my favorite name!

      Reply
Anonymous
October 24, 2014 @ 7:12 am

Hi David,

I have fair amount of knowledge in java as I have taken a java class in college. I understood about the admin part really well, but developer part needs a lot of practice. I have started reading your tutorial, also started doing some coding from the tutorial and will get the head first java book soon. So, my goal is to master the platform. Therefore, can you suggest me what should be my strategy to proceed? On what areas I should focus more? If I spend atleast 2-3 hours a day how long will it take me to learn?

Reply
    David Liu
    October 24, 2014 @ 11:24 am

    Go step by step through the tutorials in the chapters and you will be on your way to becoming a master!

    Check out this post if you haven’t already!
    https://www.sfdc99.com/2014/10/11/step-by-step-guide-to-becoming-a-salesforce-developer-this-year/

    Reply
Gates
October 15, 2014 @ 5:05 am

Forecasting is not allowed for license type is the error message received when creating a new user with this new trigger. I am running a free developer account. Sandbox doesn’t seem to be available for free editions anymore unless I missed something in the documentation.

Reply
    Gates
    October 16, 2014 @ 3:10 am

    Nevermind this, didn’t realize I had to enable forecasting in Org customization. Should have read through the comments on this chapter!

    Reply
      David Liu
      October 16, 2014 @ 8:03 pm

      ^_^

      Reply
Yemi
September 15, 2014 @ 1:17 am

for (User userInLoop : Trigger.new)

Hi David
Based on your explanation, “userInLoop” is a list of all new users during the “for” iteration .

What is the Trigger.new used for

Reply
    Alfian
    September 22, 2014 @ 1:17 am

    See on this page, number 3 question.

    Reply
S Patrick
May 20, 2014 @ 6:01 am

Hi,

I am trying the above code . But was just wondering would it run after or before creating the user. Because when I am entering the new user the checkbox is still unchecked

Reply
    David Liu
    May 20, 2014 @ 8:16 am

    It’ll run after you save it! “before insert” doesn’t mean it runs when you open up a new User page, although that is an interesting theory!!

    Reply
srujan
May 7, 2014 @ 7:31 pm

Here Why did u use before insert , with out creating the user,u can use after insert,why to waste the Runtime…..

Reply
    David Liu
    May 7, 2014 @ 10:03 pm

    Check out this post!
    https://www.sfdc99.com/2014/01/25/use-vs-triggers/

    Also, before triggers are more efficient than after triggers (they only use a single DML vs. double!)

    Reply
Anonymous
March 22, 2014 @ 10:59 am

Hi David — Question about a bigger picture around triggers? I started off writing triggers by putting the business logic inside the trigger itself but then I read somewhere that the core business logic should be in its own class. I am concerned that I may be naming my trigger class incorrectly from a bigger picture perspective.

For example, I have a use case to write a trigger on the user object; so I build my if statement logic around the insert, isupdate, etc inside the trigger and instantiate/call the actual class inside the trigger, passing it things like trigger.new, trigger map, etc. Since the current use case id specific to reporting on license tracking I called the class UserLicenseManager. However, would this become a problem when I have some other trigger use case that is on the User object but not related to tracking license usage when the new logic would perform updates, inserts, etc? Will it end up firing my UserLicenseManager class again and would that cause a problem of recursion, etc. I have read different concerns around this but I am still fuzzy on this topic and like most of your lessons the just seem to be very clear and concise.

I am wondering what is the best way to structure trigger logic and classes that make them easily scale-able.

Perhaps you have a lesson on this and I have not reached it as of yet! I am just worried that I have started creating independent class names where maybe I should have created a name like User_Trigger_Manager and had methods in that class that do the specific things like manage user license tracking, for example or some other best practice approach.

I know I have written a book here so to speak; so if you don’t respond I totally understand as I am sure you are a very busy man.

Thank you,
Tom B

Reply
    David Liu
    March 23, 2014 @ 1:04 am

    Thomas, very happy you are asking me this!

    You are correct in that it is a best practice to make a “master” trigger that simply calls individual classes, instead of creating an individual trigger for each. The main reason this format is better is because it lets you control the order of your trigger actions, whereas if you have individual triggers there is no way to control this.

    Even though the above is a best practice, it’s not that big of a deal. Most orgs don’t use that pattern and get by perfectly fine. I choose to use it because I am at a point where I need to write code that ultra-scales, but it is a bit advanced so I chose not to teach it until chapter 8 (coming soon)!

    Unless you’re doing crazy things in your trigger (ie integrations with 3rd party systems), you won’t have to worry about recursion (infinite loops) using the master trigger pattern or individual triggers. Here are a few reasons why:

    1. Triggers don’t mix DML – ie a single trigger cannot be both an insert and an update. So if you call your class in insert and in update on a master trigger, the class will only be called once max!
    http://salesforce.stackexchange.com/questions/4813/trigger-behaviour-with-insert-and-update-in-same-execution-context

    2. In before triggers, your changes don’t save until all code has finished. This means that no matter how many classes are called, the actual “update” only happens at the very end, preventing recursion.

    3. In after triggers, you can’t call an “update” on records in your trigger. Salesforce won’t let you save your code if you try! There’s a hack to bypass this, but Salesforce will notice that recursion is happening and throw an error when you run the code anyway.

    The only realistic way to have recursion in Salesforce is if you call a third party tool after records are updated, then the third party tool calls Salesforce to update the same record, then lather rinse and repeat!

    Anyway hopefully this wasn’t confusing. Long story short recursion will never happen, but good job considering it =)
    David

    Reply
      Anonymous
      March 23, 2014 @ 9:52 am

      Once again — thank you for your clear, concise response; it was extremely helpful to me!

      Reply
      Neha
      May 12, 2014 @ 3:43 am

      Hi man..

      Can u please explain your Third Point in brief. I am not able to understand indetail.

      Thanks

      Reply
        David Liu
        May 12, 2014 @ 6:28 pm

        Hey Neha! Which one are you talking about? (Sorry!)

        Reply
      radha
      February 14, 2015 @ 9:24 pm

      in second point the update may not happen but the code is called again and again so will it throw error?
      ex
      the code in trigger a on object a before insert is doing insert object b
      the code in trigger b on object b before insert is doing insert on object a
      sorry if it is a silly question

      Reply
Vipul Jaisinghani
February 28, 2014 @ 5:26 am

Hi David,

I have recently started to learn triggers from your website.. its of great help really.. :) i have been trying to write a cross object trigger.. such that if a contact becomes a campaign member its lead status becomes ‘Open – Not Contacted’. lead status is a picklist.. this is the first trigger I have ever written.. I dont want it to be my last.. so please help… :)

trigger Blank on CampaignMember (before insert)
{
for (CampaignMember userInLoop : Trigger.new)
{
userInLoop.Contact.Lead_Status__c = ‘Open – Not Contacted’;
}
}
its giving me an error..
Apex trigger Blank caused an unexpected exception, contact your administrator: Blank: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.Blank: line 5, column 1

Reply
    David Liu
    March 2, 2014 @ 4:04 pm

    I think your trigger is getting confused between Contacts and Leads, since remember that Campaign Members can be either!

    I’m guessing you meant leads – if so, make sure to change all references to “Contact” to “Lead” instead!

    Reply
      Vipul Jaisinghani
      March 3, 2014 @ 1:41 am

      Hey David,

      Thanks for replying… but I am actually working on Contacts and not leads. In my SFDC instance contacts also have a field called as lead Status. My clients have customized it in such a way that leads are first converted to contacts and contacts are than added to campaign as a campaign member.

      Reply
        David Liu
        March 3, 2014 @ 10:29 pm

        Try using the trick that I use in this post to get a related object:
        https://www.sfdc99.com/2014/03/02/change-your-code-on-the-fly-using-custom-settings/

        (Grab the Contact just like I grab the Account)

        Also, make sure the Contact is not null before proceeding! For example, if Leads are uploaded you’ll get an error every time.

        David

        Reply
    Anonymous
    April 23, 2014 @ 12:24 am

    vipul i wnt to ask something more about salesfoce..so cn u pls provide me with ur email id
    or u can just mail me at jubisha.244@gmail.com.
    will wait fr ur reply.

    Reply
      David Liu
      April 23, 2014 @ 9:37 pm

      Are you talking to me? Lol!

      Reply
Madhu
February 24, 2014 @ 3:49 am

Really a great piece of code….

Thanks a lot David, you are doing really amazing…

Reply
    David Liu
    February 24, 2014 @ 6:51 pm

    No problem, I enjoy it!

    Reply
Andrew Zoorob
November 29, 2013 @ 9:37 pm

Hi David. Just wanted to say thanks for this awesome site! Great material, and I love your style of explaining.

Reply
kumar
October 17, 2013 @ 5:32 pm

Tutorial is really very good……Thank you for making apex coding life also easy these days….

Thanks a tone …..

Is ForcastEnabled = true; not work for developer edition?

i am getting error when I am trying the code to execute…

Thanks,

Reply
    David Liu
    October 17, 2013 @ 10:12 pm

    Thanks Kumar!

    Can you copy the specific error message you’re getting? I’m using a developer edition too and this works 100%!

    Here are a couple more things to check:
    – Is there an “Allow Forecasting” checkbox available on a user’s detail page?
    – Go to Setup >> Customize >> Forecasts >> Settings and enable forecasting!

    Let me know if this fixes it!
    David

    Reply
Chris
October 13, 2013 @ 11:01 am

How you go into detail on everything is so helpful! I feel like I’m being calmly walked through parts of a sentence in elementary school. LOVE IT

Reply

Leave a Reply Cancel reply

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


*

*

Theme: Simple Style by Fimply