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!
David…just recently sent you an e-mail..actually found your site afterwards…coming together more clearly now thanks.
I just wrote my first Apex trigger – the first of many more! Thank you, David.
Proud of you Catherine!!!!
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
Thank you Bryce!!
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!
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
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
Check out surveyforce which does this – you can see all the code inside it once you download it!
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
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];
}
That’s it =)
Another thing you can do is create an Integer variable outside the trigger, then increment it inside.
Wow! Great idea Thanks!
hello David ..please enplane uses of Trigger.New
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
Use the salesforce license to create an user. it worked for me
Hi,
Cant we update the picklist values for the standard object say Locale to somehthing with this code.
Found it in the next section in Apex class,for LocaleSidKey = ‘en_US’
Where can we see for the avaliable picktlist values for LocaleSidKey .
Check this page out!
https://help.salesforce.com/apex/HTViewHelpDoc?id=admin_supported_locales.htm
Sundar is my favorite name!
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?
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/
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.
Nevermind this, didn’t realize I had to enable forecasting in Org customization. Should have read through the comments on this chapter!
^_^
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
See on this page, number 3 question.
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
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!!
Here Why did u use before insert , with out creating the user,u can use after insert,why to waste the Runtime…..
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!)
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
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
Once again — thank you for your clear, concise response; it was extremely helpful to me!
Hi man..
Can u please explain your Third Point in brief. I am not able to understand indetail.
Thanks
Hey Neha! Which one are you talking about? (Sorry!)
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
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
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!
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.
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
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.
Are you talking to me? Lol!
Really a great piece of code….
Thanks a lot David, you are doing really amazing…
No problem, I enjoy it!
Hi David. Just wanted to say thanks for this awesome site! Great material, and I love your style of explaining.
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,
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
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