function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Kanishka JaroliKanishka Jaroli 

Update custom fields on all child records when updation of same fields on that field on parent occurs. using trigger

I have 2 custom objects: Student and Registration.They have a same field class. Registration has a lookup to Student. I need to update all related registration records's class field when the class of student is updated using triggers. (A student can have multiple registrations)
Thanks in advance.
Best Answer chosen by Kanishka Jaroli
Ajay K DubediAjay K Dubedi
Hi Kanishka,
Please try the below code.
//Trigger:

trigger UpdateChildObjectFields on Student__c (after insert, before update)
{
 
         ChangeClassName.ChangeClassName(trigger.new);
     
}

// Apex Class:

public class ChangeClassName 
{
 public static void ChangeClassName(List<Student__c> Customlist)
 {
     set<Id> setid=new set<Id>();
     for(Student__c floop:Customlist)
     {
        setid.add(floop.Id);
     }
     
     List<Registration__c> Newlist=new List<Registration__c>();
     Newlist=[SELECT name,Class__c,Student__c from Registration__c where Student__c IN:setid];
     List<Registration__c> newreglist=new List<Registration__c>();
     
     for(Student__c st : Customlist)
     {
    for(Registration__c reg : Newlist)
    {
       if(reg.Student__c==st.Id)
       {
           reg.Class__c=st.Class__c;
           newreglist.add(reg);
       }
    }
    }
     upsert newreglist;
 }
}

Please mark it as a best if it helps you.

Thanks,
Ajay Dubedi

All Answers

Shruti SShruti S
I would suggest you to do this via point and click. You can use Processes for this scenario. Below are the steps for creating a Process for this use case:
  1. Create a Process on Student__c object for everytime a record is created or edited.
  2. Use record update feature in Process Builder to update the class field on the child records (i.e Registration object records) .
  3. Activate the Process.
Please let me know if you have any more doubts.
Kanishka JaroliKanishka Jaroli
I am supposed to do this using trigger only
Ajay K DubediAjay K Dubedi
Hi Kanishka,
Please try the below code.
//Trigger:

trigger UpdateChildObjectFields on Student__c (after insert, before update)
{
 
         ChangeClassName.ChangeClassName(trigger.new);
     
}

// Apex Class:

public class ChangeClassName 
{
 public static void ChangeClassName(List<Student__c> Customlist)
 {
     set<Id> setid=new set<Id>();
     for(Student__c floop:Customlist)
     {
        setid.add(floop.Id);
     }
     
     List<Registration__c> Newlist=new List<Registration__c>();
     Newlist=[SELECT name,Class__c,Student__c from Registration__c where Student__c IN:setid];
     List<Registration__c> newreglist=new List<Registration__c>();
     
     for(Student__c st : Customlist)
     {
    for(Registration__c reg : Newlist)
    {
       if(reg.Student__c==st.Id)
       {
           reg.Class__c=st.Class__c;
           newreglist.add(reg);
       }
    }
    }
     upsert newreglist;
 }
}

Please mark it as a best if it helps you.

Thanks,
Ajay Dubedi
This was selected as the best answer
PreyankaPreyanka
Hello Kanishka,

It is always better to use out of the box functionality of Salesforce if that caters your requirement. But as you want to impement it via trigger please find the code below:
//Trigger on Student Object
trigger StudentTrigger on Student__c (after insert, after update) {
    
    if(Trigger.isAfter){
        if(Trigger.isUpdate){
            Map<Id, String> mapChangeStudentClass = new Map<Id, String>();
            //Used to find whose Class field was changed
            for(Student__c objStudent: Trigger.New){
                for(Student__c objStudentOld: Trigger.Old){
                    if(objStudent.Id == objStudentOld.Id){
                        if(!(objStudent.Student_Class__c).equalsIgnoreCase(objStudentOld.Student_Class__c)){
                            mapChangeStudentClass.put(objStudent.Id, objStudent.Student_Class__c);
                            break;
                        }
                    }
                }
            }
            
            if(mapChangeStudentClass != null && mapChangeStudentClass.size()>0){
                List<Registration__c> lstRegistration = new List<Registration__c>();
                List<Registration__c> lstUpdateRegistration = new List<Registration__c>();
                //Get all the related Registration with Student object
                lstRegistration = [select Id, Registration_Class__c, Student__c,Student__r.Id  from Registration__c where Student__c in :mapChangeStudentClass.keySet()];
                
                if(lstRegistration != null && lstRegistration.size()>0){
                    for(Registration__c objRegistration:lstRegistration){
                        if(mapChangeStudentClass.containsKey(objRegistration.Student__r.Id)){
                            objRegistration.Registration_Class__c = mapChangeStudentClass.get(objRegistration.Student__r.Id);
                            lstUpdateRegistration.add(objRegistration);
                        }
                    }
                    //Update the Class field of Registration
                    if(lstUpdateRegistration != null && lstUpdateRegistration.size()>0){
                        Database.update(lstUpdateRegistration);
                    }
                }
            }
        }
    }

}
Its better to use trigger framework but as of now I have just write the code in Trigger itself.

Thanks
Preyanka

 
Shruti SShruti S
I would still highly recommend you to use Processes. You should always convince the concerned people that Salesforce always recommends you to use point and click as opposed to writing Apex. One of the major advantage of using Processes is 
  1. Less Maintenaince
  2. Easy Deployment
  3. Facilitates making changes easily
  4. No need of writing unit tests
It was for this main reason that Process was introduced. I always recommend Processes if possible.

That being said, if you really want to know how the Trigger would look like - 
trigger StudentTrigger on Student__c ( after Insert, after Update ) {
    if( Trigger.isAfter ) {
        if( Trigger.isInsert || Trigger.isUpdate ) {
            Map<String,String> mapOfStuIdToClass = new Map<String,String>();
            
            for( Student__c stuNew : Trigger.new ) {
                Student__c stuOld = Trigger.oldMap.get( stuNew.Id );
                if( stuNew.Class__c != stuOld.Class__c ) {
                    mapOfStuIdToClass.put( stuNew.Id, stuNew.Class__c );
                }
            }
            
            if( !mapOfStuIdToClass.isEmpty() ) {
                List<Registration__c> registrations = new List<Registration__c>();
                
                registrations = [
                    SELECT  Class__c
                    FROM    Registration__c
                    WHERE   Student__c IN :mapOfStuIdToClass.keyset()
                ];
                
                for( Registration__c reg : registrations ) {
                    reg.Class__c = mapOfStuIdToClass.get( reg.Student__c );
                }
                
                UPDATE registrations;
            }
        }
    }
}
Like as mentioned by the other folks, you should never write the business logic within the Trigger. It becomes difficult to maintain and the order of execution becomes unpredictable. That being said, I have written it within the Trigger for the sake of simplicity. You should try using a Trigger Pattern which is easy for you to understand.

Good Luck!