Basic Apex Trigger Examples:
1.DemoTtrigger1
DemoTtrigger1 Populates Description field with the user first name who creates or updates the record by using userInfo standard keyword . And also does not allow user to delete the record .
trigger DemoTtrigger1 on Author__c (before insert,before update,before delete) {
If(trigger.isInsert){
for(Author__c Author: Trigger.new){
//Populates Description with the user first name who creates the record
Author.Description__c = 'Author Created by '+ userInfo.getFirstName();
}
} else
If(trigger.isUpdate){
for(Author__c Author: Trigger.new){
//Updates Description with the user first name who updates the record
Author.Description__c = 'Author Last updated by '+ userInfo.getFirstName();
}
}
if(Trigger.isDelete&&Trigger.isbefore){
for(Author__c Rec:trigger.old)
{
//User gets the below error when user tried to delete the record
Rec.adderror('You Cannot Delete the Author Record');
}
}
}
2.DemoTrigger2
Whenever new account record creates"Account_Rep__c" updates with the account owner name.
trigger DemoTrigger2 on Account (before insert) {
Set<Id>setAccOwner=new Set<Id>();
for(Account Acc: trigger.new)
{
setAccOwner.add(Acc.OwnerId);
}
map<id,user>userMap=new map<id,user>();
for(user u:[select id,Name from user where id IN:setAccOwner]){
userMap.put(u.id,u);
}
for(Account Acc: Trigger.new)
{
User usr=UserMap.get(Acc.OwnerId);
system.debug('usr');
Acc.Account_Rep__c=usr.Name;
}
}
Note :Most of the examples here made use of Map/List .If you are not sure about the Map/List concepts ,Please make use of below post which clearly explains about collections in salesforce .
https://salessforcehacks.blogspot.com/2020/01/collections-in-salesforce-list-set-map.html
3.DemoTrigger3
DemoTrigger3 prevents user to delete contact which is associated with the any account. When user tries to delete associated contact ,User will be presented with the error "Contact associated with account cannot be deleted"
trigger DemoTrigger3 on Contact (before delete) {
//Contact with associated account cannot be deleted
if(Trigger.isDelete&&Trigger.isbefore){
for(contact con:Trigger.old){
if(con.accountId!=null){
con.addError('Contact associated with account cannot be deleted');
}
}}
4.DemoTrigger4
Creates opportunity record if the account doesn't contain at least one opportunity.
trigger DemoTrigger4 on Account(after insert, after update) {
List<Opportunity> oppList = new List<Opportunity>();
// Get the related opportunities for the accounts in this trigger
Map<Id,Account> acctsWithOpps = new Map<Id,Account>(
[SELECT Id,Name,(SELECT Id,Name FROM Opportunities) FROM Account WHERE Id IN :Trigger.New]);
System.debug('acctsWithOpps ::'+acctsWithOpps);
// Add an opportunity for each account if it doesn't already have one.
// Iterate through each account.
for(Account a : Trigger.New) {
System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size());
// Check if the account already has a related opportunity.
if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) {
// If it doesn't, add a default opportunity
oppList.add(new Opportunity(Name=a.Name + ' Opportunity',
StageName='Prospecting',
CloseDate=System.today().addMonths(1),
AccountId=a.Id));
}
}
if (oppList.size() > 0) {
insert oppList;
}
}
5.DemoTrigger5
DemoTrigger5 send email notification after new student record created into the system. Trigger makes use of handler class to send an email notification. Trigger collects newly created student records and send them to the handler class to process further for the email notification.
trigger DemoTrigger5 on student__c (After insert) {
if(Trigger.isinsert&&Trigger.isafter){
StudentEmailNotification.sendMail(Trigger.new);
}
}
class :
public class StudentEmailNotification {
// Public method
public static void sendMail(List<student__c> stuList) {
// Create an email message object
system.debug('stuList in sendmail method :'+stuList);
for(student__c st :stuList){
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
String address=st.Email__c;
String[] toAddresses = new String[] {address};
String ccAddresses=st.Class_Owner_Email__c ;
system.debug('ccAddresses :'+ccAddresses);
String[] setCcAddresses=new String[] {ccAddresses};
mail.setToAddresses(toAddresses);
mail.setCcAddresses(setCcAddresses);
mail.setSubject('Student Registration Notification');
mail.setPlainTextBody
('The Student' + st.Name + ' Registration is Completed with the below details :'+'\n\n' +
'Student Name : ' + st.Name + '\n\n'+
'Request Email : ' +st.Email__c + '\n\n' +
'Class: ' +st.Class__c+ '\n\n' +
'Please reach out to System Administrator if you require any further information');
Messaging.SendEmailResult[] results = Messaging.sendEmail(
new Messaging.SingleEmailMessage[] { mail });
}
}
}
6.DemoTrigger6
Updates "Associated_Contacts__c" with the number of contacts associated with the account . Whenever new contact creates/removed from the account ,The respective count would be increased/Decreased accordingly.
trigger DemoTrigger6 on Contact (before delete,before insert,after insert,after delete,after update) {
//Update count of the contact to the 'Associated Contacts' field in the account
set<id> accid=new set<id>();
list<contact> contactlist =new list<contact>();
list<contact> listcon=new list<contact>();
list<account> listAcc=new list<account>();
list<account> acclist=new list<account>();
map<id,integer> mapCount=new map<id,integer>();
if(trigger.isinsert){
for(contact con:trigger.new){
accid.add(con.accountid);
}
}
if(trigger.isdelete){
for(contact con:trigger.old){
accid.add(con.accountid);
}
}
acclist=[select id,name,Overall_Contacts_Status__c from account where id in:accid];
contactlist = [select id,Status__c,name,accountid from contact where accountid in:accid];
for(account acc:acclist){
listcon.clear();
for(contact c:contactlist){
if(c.accountid==acc.id){
listcon.add(c);
}
}
mapCount.put(acc.id,listcon.size());
}
if(acclist.size()>0){
for(Account a:acclist){
if(mapCount.get(a.id)==null)
a.Associated_Contacts__c=0;
else
a.Associated_Contacts__c=mapCount.get(a.id);
listAcc.add(a);
}
}
if(listAcc.size()>0)
update listAcc;
}
//you can also reduce the code with account inner query like below
trigger DemoTrigger6 on Contact (before delete,before insert,after insert,after delete,after update) {
set<id> accountIds=new set<id>();
List<account> accList=new List<account>();
map<id,integer> noOfContacts=new map<id,integer>();
List<account> updateaccList=new List<account>();
if(Trigger.isinsert||Trigger.isUpdate&&Trigger.isafter){
for(contact con:Trigger.new){
if(Trigger.isinsert){
accountIds.add(con.accountId);
}else if(Trigger.isUpdate&&trigger.oldmap.get(con.id).accountId!=null&&con.accountId==null){
accountIds.add(trigger.oldmap.get(con.id).accountId);
}
}
}
if(Trigger.isDelete&&Trigger.isafter){
for(contact con:Trigger.old){
accountIds.add(con.accountId);
}
}
system.debug('accountIDs:'+accountIds);
accList=[select id,(select id,accountId from contacts) from account where id IN:accountIds];
for(account acc:accList){
if(acc.contacts.size()>0){
acc.Associated_Contacts__c=acc.contacts.size();
}else{
acc.Associated_Contacts__c=0;
}
updateaccList.add(acc);
}
system.debug('updateaccList:'+updateaccList);
update updateaccList;
}
7.DemoTrigger7
DemoTrigger7 helps to avoid recursive trigger by using the handler.
trigger DemoTrigger7 on Account (after insert) {
if(RecursionExampleHandler.isFirstTime){
RecursionExampleHandler.isFirstTime=false;
for(account a:Trigger.new){
account acc=new account();
acc.Name='Recursive Test';
insert acc;
}
}
}
class :
public class RecursionExampleHandler {
public static Boolean isFirstTime=True;
}
You can also visit below post to know more about recursive trigger scenario
https://salessforcehacks.blogspot.com/2019/12/salesforce-recursive-triggers-fully.html
8.Apex Managed Sharing :
Until now Most of us know the methods of sharing the records across organization by using sharing rules and OWD ,This example helps us to share records in programmatic way(Apex Trigger/Apex Class) for the complex business requirements .
Scenario Based Example:
Prerequisite:
Objects Used in the discussion:1.Project--Object contains all the business task details which require to be completed .
2.Project Member--Are the members who work on the project which has assigned to them.
Project Member is junction object which is master-Detail with Project and Contact
3.Contact--Sales force Contact Object
Assume all the contacts Owner is assigned with their own User ID .
Eg .We have user Kris who is also Owner for associated contact named Kris .
Use Case :
1.Whenever status of the project changed from 'New' to 'Assigned' The respective project record access should be shared with all the Project Members .2.Once the Project Members completed their assigned task and Status of the Project changes to 'Completed' then Access should be Revoked/Removed from the Project Team Members .
Solution:
We require to create Apex Trigger on Project object and create the share object records and delete the access after Project completedThe below Trigger collects all the project records for which status changed to 'Assigned' Or changed to 'Completed' and send them to Apex class to create and Revoke the access respectively by using apex sharing .
Apex Trigger :
trigger ProjectShare on Project__c (after update) {List<Project__c > projectShareList=new List<Project__c >();
List<Project__c > revokeShareList=new List<Project__c >();
//Share the access
if(Trigger.isafter&&Trigger.isUpdate){
for(Project__c Pro:Trigger.new){
if(Pro.Status__c=='Assigned'&&trigger.oldmap.get(Pro.id).Status__c!='Assigned'){
projectShareList.add(Pro);
system.debug('Share the access'+Pro.id);
}
}
if(projectShareList!=null){
ProjectShareclass.provideAccess(projectShareList);
}
//Revoke the access
for(Project__c Pro:Trigger.new){
if(Pro.Status__c!='Assigned'&&trigger.oldmap.get(Pro.id).Status__c=='Assigned'){
system.debug('Revoke the access'+Pro.id);
revokeShareList.add(std);
}
}
if(revokeShareList!=null){
ProjectShareclass.revokeAccess(revokeshareList);
}
}
}
Apex Class :
public static void provideAccess(List<Project__c > pros){List<Project_member__c> tmList=new List<Project_member__c>();
map<id,Project_member__c> tmmap=new map<id,Project_member__c>();
List<Project__Share> shareList=new List<Project__Share>();
tmList=[select id,project__c,MasterDetailWithcontact__r.owner.id from Project_member__c where Project__c IN:pros];
for(Project_member__c s:tmList){
tmmap.put(s.Project__c,s);
}
for(Project__c rec:Pros){
Project__Share share=new Project__Share();
share.ParentId = rec.id;
share.AccessLevel = 'Edit';
share.RowCause = Schema.Project__Share.RowCause.Manual;
share.UserOrGroupId = tmmap.get(rec.id).MasterDetailWithcontact__r.owner.id;
shareList.add(share);
}
insert shareList;
}
public static void revokeAccess(List<Project__c> pros){
List<Project__Share> shareList=new List<Project__Share>();
shareList=[select id from Project__Share where parentId IN:pros AND RowCause = 'Manual'];
delete shareList;
}
}
Result :
Once the project record is created into the database ,By default only owner of the record will have access to record as shown in Screenshot 2 :Screenshot 2:
Once the above project record updated to the 'Assigned' status ,Access of the project record will be shared to project team member . Please find the ScreenShot 3.
First Share record with all access Level belongs to the default record owner access . And Second Share record with Edit access and RowCause 'Manual' belongs to Share record created by above Apex trigger and Apex class.
ScreenShot 3 :
If you update the Status to 'Completed' again the 'Edit' access would be revoked/Deleted to all the Project Members associated to Project object.
*********************************************************************
What is apex trigger in salesforce,Triggers in salesforce,Apex triggers,Basic apex trigger examples in salesforce,Apex trigger real time scenarios ,apex trigger with hands on examples.
*********************************************************************
We hope you are clear with the process now .
If you still require further clarifications,Please let us know in the comments .
Please follow us for more salesforce concepts.
Happy Learning☺☺☺
This is applicable to lightning yes?
ReplyDeleteThank you mate .examples are very clear
ReplyDeleteIf I'm not wrong we can only use (before delete) event in 3rd example.
ReplyDeleteI learned many basics still not able to write code.Please help me out on this.give me some technics
ReplyDeleteIf u start writing a code try to put more system.debug on each line so that u can understand line by line what was the executing while running a trigger
ReplyDeleteThanks for the valuable Content. I really learned a lot here. Do share more like this.
ReplyDeleteSales Force Testing
Salesforce Automation Testing
Very useful information
ReplyDeleteSalesforce Online Training
Very useful information
ReplyDeleteFantastic breakdown in Salesforce! The article succinctly covers key terminology, characteristics, and practical tips. Super helpful for anyone navigating Salesforce development. Kudos to the author for such valuable insights.
ReplyDeleteGreat insights on Salesforce ! Clear and helpful breakdown. Excited to apply these tips in my projects. Thanks for sharing
Salesforce Time Tracking Integration