+ Start a Discussion
Benjamin OliverBenjamin Oliver 

Simple Trigger Question

Hi Community,

I am new to Salesforce and using APEX.  I am completely self-taught too.  With that said, I am trying to learn triggers and cannot find an exact example of how to achieve what I am working on.  My problem is that when a Contact updates their information through my Visualforce page, Salesforce will overwright fields with the new data they inputted - which is great, except for the 'Description' field.  I want the new 'Description' to append to whatever they previously had written in that field.  Can anyone help me?

The pseudo code would be something like:

trigger UpdateDescription on Contact (before update) {
          Contact.Description = Contact.OldDescription + " " + Contact.NewDescription;

}

Thank you in advance for your help!

Thiyagarajan Selvaraj (SFDC Developer)Thiyagarajan Selvaraj (SFDC Developer)
Hi Benjamin,

You could do like 
 
trigger UpdateDescription on Contact (before update) {
	for(Contact contact : trigger.new){
		Contact.Description = trigger.oldMap.get(contact.Id).Description  + " " + Contact.Description;
	}
}

Thanks,
 
pranab khatuapranab khatua
trigger UpdateDescription on Contact (before update) {
	for(Contact c: trigger.new){
		c.description = trigger.oldMap.get(c.Id).description+ ' '+ c.description;
	}
}
Benjamin OliverBenjamin Oliver
Thank you for the responses!  Is there a way to perhaps add a timestamp and a new line?  It will make it easier to see where the original data ends and new appended data begins.  Thank you in advance!
pranab khatuapranab khatua
trigger UpdateDescription on Contact (before update) {
	for(Contact c: trigger.new){
		c.description = trigger.oldMap.get(c.Id).description+  '\r\n' + System.now()+  '\r\n' + c.description;
	}
}
Benjamin OliverBenjamin Oliver

Hello, 
I implemented Pranab's code that he last posted - however, I have a problem.  When I delete the Description field on the contact profile page, it won't delete the field!  I think it is appending the old description to a blank description (because I highlight all the text in the textbox and hit delete, then save).  How can I get around this?

Thank you!

Lars NielsenLars Nielsen
A small tweak to Pranab's code is below that just checks the value and if trigger.new is empty you know you are trying to whipe out the value and it allows that to happen.
 
trigger UpdateDescription on Contact (before update) {
    for(Contact c: trigger.new){
     
        if(c.description == '' || c.description == null)
            c.description = null;
        else if(c.description != '' || (trigger.oldMap.get(c.Id).description != ''))
        {   
            string oldDesc = trigger.oldMap.get(c.Id).description;
            if (oldDesc == null) //avoid printing out null
                oldDesc = '';
            c.description = oldDesc  +  '\r\n' + System.now()+  '\r\n' + c.description;
        }
    }
}

 
Benjamin OliverBenjamin Oliver

Lars, thank you for your help!  Unfortunately, this is giving me a problem.  Everytime someone edits anything on the Contact profile and hits 'Save', the Description is duplicated and appended to itself with an extra timestamp.  How can I fix this?  Thank you so much!

Lars NielsenLars Nielsen
You would need to take that into account with another condition.
 
trigger UpdateDescription on Contact (before update) {
    for(Contact c: trigger.new){
     
     string oldDesc = trigger.oldMap.get(c.Id).description;
      if (oldDesc == null || oldDesc  == '') //avoid printing out null
            oldDesc = '';
     
     //case 1 - description is already empty and no new data was entered
     //case 2 - also covers scenario where user clears the description field
     if(c.description == '' || c.description == null)
     {
         c.description = '';
         break;
     }
         
     //case 2 - description is empty and being added by user    
     else if((c.description != '' || c.description != null) && (oldDesc == ''))
     {
        c.description = System.now()  + '\r\n' + c.description;
        break;
     }
    //case 3 - description is not empty and we are appending to the last description present
    else if((c.description != '' && c.description != null) && (oldDesc != '') && (c.description != oldDesc))
    {
        System.Debug('c.description = ' + c.description);
        System.Debug('oldDesc = ' + oldDesc);
        c.description =  '\r\n' + System.now()+  '\r\n' + c.description;
        break;
    }

    }
}



In all the code adove and previous samples people have submitted Description = Old Description + new line + Time plus New Description. The issue is that Old and New  will be the same if the user edits the record but doesn't change the description. If you truly want to solve this where it works like an audit trail you're going to have to take a different approach where you try to parse out only what got appended and stick a timestamp in front of just the new /removedportion. In the case above I remove adding "oldDesc" from the  second to last line before the break
 
c.description =  '\r\n' + System.now()+  '\r\n' + c.description;

Like I said, it depends on where you stick the Time and new lines as to how it looks at the end.
Benjamin OliverBenjamin Oliver

Hi Lars,

Thank you so much!  That code works when I edit anything on the Contact profile page and appends correctly.  However, I am using a VisualForce page to collect Contact data.  They fill out a Description textbox and that gets updated into the Contact's Description field.  For some reason, when the data comes from my VisualForce page, it completely overwrites the Description field.  Why is this?  Can the trigger fix this?  Ideally, I want the data from my VisualForce page's Description field to append onto my Contact's Description field.  

Thank you so much Lars! 

Benjamin OliverBenjamin Oliver

Hi Lars,

Could anyone provide any additional insights to my issue described above?  Thank you.

Thank you in advance!

Lars NielsenLars Nielsen
Given that you are using a custom Visualforce page and not the default contact page, my guess is you are also using the default controller. You may have to override the standard contact controller (i.e. extend it)
https://developer.salesforce.com/docs/atlas.en-us.200.0.pages.meta/pages/pages_controller_extension.htm

Without seeing the source it is hard to say. If it all works in the standard Contact page but acts differently through your custom visualforce page then my guess is the issue is with the VF page/controller code.
Benjamin OliverBenjamin Oliver

Hi Lars,

I agree, and these were my initial thoughts too.  As you can see in my controller, I am extending the standard contact controller - however, I am still lost at how/where/why it is not functioning correctly when updating through my VF Page/Controller.  Additionally, I've added the code for my controller and VF page.  Please let me know what you think, I've looked everything multiple times and can't find the bug!  Thank you so much for your support, Lars!  You've been great!

My controller:

public class Contact_Update_Controller 
{
    public List<DependentWrapper> wrappers {get; set;} 
    public Contact contact {get; set;}
    public static Integer toDelIdent {get; set;}
    public static Integer addCount {get; set;}
    private Integer nextIdent=0;
  
    public Contact_Update_Controller(ApexPages.StandardController controller)
    {
       contact = (Contact)controller.getRecord();       

       wrappers=new List<DependentWrapper>();
       for (Integer idx=0; idx<1; idx++)
       {
          wrappers.add(new DependentWrapper(nextIdent++));
       }
    }
  
    //delete row in wrapper
    public void delWrapper()
    {
       Integer toDelPos=-1;
       for (Integer idx=0; idx<wrappers.size(); idx++)
       {
          if (wrappers[idx].ident==toDelIdent)
          {
              toDelPos=idx;
          }
       }
   
       if (-1!=toDelPos)
       {
           wrappers.remove(toDelPos);
       }
    }
    
    //add row to wrapper
    public void addRows()
    {
        for (Integer idx=0; idx<addCount; idx++)
        {
            wrappers.add(new DependentWrapper(nextIdent++));
        } 
    }
  
    //checks if contact exists, updates contact information, creates event/task to log/track activity
    public PageReference save()
    {
        if(contact!=null)
        {
        
        //checks if contact exists in database 
        List<Contact> contacts = [SELECT Id, (select Id from Dependents__r) FROM Contact WHERE Phone = :contact.MobilePhone OR MobilePhone = :contact.MobilePhone];
        
        //populates contact with timestamp for sizing information
        if(contacts.size() != 0)
        {
             contact.Id = contacts[0].Id;
             contact.Diaper_Size_Date__c = System.now().Date();
             contact.Clothing_Size_Date__c = System.now().Date();
             contact.Shoe_Size_Date__c = System.now().Date();
             update contact;
        }
        else
        {
             return new PageReference('/apex/Create_Lead_Not_Update_Contact');
        }
        
        //inserts or updates dependent information
        List<Dependent__c> deps = new List<Dependent__c>();
        for (DependentWrapper wrap : wrappers)
        {
            if(wrap.dep.Name != null)
            {
                for (Contact curCon : [SELECT id, name, (SELECT id, name FROM Dependents__r) FROM Contact WHERE id=:contact.id])
                {
                    for (Dependent__c oldDep : curCon.dependents__r)
                    {
                        if (wrap.dep.Name == oldDep.Name)
                        {
                            wrap.dep.Id = oldDep.Id;
                            break;
                        }
                    }
                
                    if (wrap.dep.Id == null)
                    {
                        wrap.dep.Contact__c = contacts[0].Id;
                        wrap.dep.Formula_Date__c = System.now().Date();
                        wrap.dep.Clothing_Size_Date__c = System.now().Date();
                        wrap.dep.Shoe_Size_Date__c = System.now().Date();
                        wrap.dep.Diaper_Size_Date__c = System.now().Date();
                        
                        insert wrap.dep;
                    }
                    else
                    {
                        wrap.dep.Contact__c = contacts[0].Id;
                        wrap.dep.Formula_Date__c = System.now().Date();
                        wrap.dep.Clothing_Size_Date__c = System.now().Date();
                        wrap.dep.Shoe_Size_Date__c = System.now().Date();
                        wrap.dep.Diaper_Size_Date__c = System.now().Date();
                
                        update wrap.dep;
                    }
                }
            }
        }
        
        Account acct = new Account();
        Contact curContact = contacts.get(0);
        
        //create task
        Task myTask = new Task();
        myTask.OwnerId = UserInfo.getUserId();
        myTask.WhoId = curContact.Id;
        myTask.Subject = 'Open Request';
        myTask.priority= 'Normal';
        myTask.status = 'Not Started';
        myTask.description = 'Submitted online application for additional assistance.';

        insert myTask;

        //create event
        Event myEvent = new Event();
        myEvent.OwnerId = UserInfo.getUserId(); 
        myEvent.WhoId = curContact.Id;
        myEvent.Subject = 'Submitted Online Form';
        myEvent.Type = 'Other';
        myEvent.Description = 'Submitted online application for additional assistance.'; 
        Datetime myDateTime = DateTime.Now();
        myEvent.StartDateTime = myDateTime;
        Datetime newDateTime = myDateTime.addHours(1);
        myEvent.EndDateTime = newDateTime;
        //E.WhatId = ''; //record id
        
        insert myEvent;
        
        return new PageReference('/apex/Lead_Registration_Complete');
        }
        else
        {
        return new PageReference('/apex/InMaintenance');
        } 
    }
    
    public class DependentWrapper
    {
        public Dependent__c dep {get; set;}
        public Integer ident {get; private set;}
   
        public DependentWrapper(Integer inIdent)
        {
        ident=inIdent;
        dep = new Dependent__c();
        }
    }
}

 

My VF Page:

<apex:page standardController="Contact" extensions="Contact_Update_Controller" showHeader="false">
<apex:form >
  <apex:pageBlock title="WE MEET NEEDS OF PEOPLE IN CRISIS">
              <apex:pageBlockSection title="Please update all fields so we may better serve you" columns="1">
              <apex:outputText ><b>Please Fill In Your Contact Information</b></apex:outputText>
                  <apex:inputField value="{!contact.FirstName}" required="true"/>
                  <apex:inputField value="{!contact.LastName}" required="true"/>
                  <apex:inputField value="{!contact.People_Affected__c}" label="# People in your family: "/>
                  <apex:inputField label="Mobile Phone" value="{!contact.MobilePhone}" required="true"/>
                  <apex:inputField value="{!contact.Email}"/>
                  
                  <apex:outputText > <b>If you have moved, update your address.</b> </apex:outputText>
                  <apex:inputField label="Street & Apartment Number" value="{!contact.MailingStreet}"/>
                  <apex:inputField value="{!contact.MailingCity}"/>
                  <apex:inputField value="{!contact.MailingState}"/>
                  <apex:inputField value="{!contact.MailingPostalCode}"/>
                  
                  <apex:outputText > <b>Please update us with the following information</b></apex:outputText>
                  //*************THIS IS WHERE DESCRIPTION IS**************//
                  <apex:inputField value="{!contact.Description}" label="Please update us about your situation and why you need our help. " style="width: 360px; height: 100px" />
                  <apex:inputField value="{!contact.Need_Household_Items__c}" label="Do you need household items?"/>
                  <apex:inputField value="{!contact.Household_Items__c}" label="If so, list items needed:"/>
                  
                  <apex:outputText ><b>Do you need clothing or shoes for yourself? If so, please fill out sizes below.</b></apex:outputText>
                  <apex:outputText ><b>You can fill in children and other family member's details below.</b></apex:outputText>
                  <apex:inputField value="{!contact.Clothing_Size__c}" label="What is your clothing size?"/>
                  <apex:inputField value="{!contact.Shoe_Size__c}" label="What is your shoe size?"/>
                  <apex:inputField value="{!contact.Diaper_Size__c}" label="Do you use adult diapers? If so, what is your size?"/>
                  
          </apex:pageBlockSection>
              
  <apex:pageBlockSection title="If you have any new family members or any sizes have changed, please fill in below." columns="1" collapsible="true">
         <apex:pageBlockTable value="{!wrappers}" var="wrapper" id="wtable">
         
         <apex:column headerValue="Line" rendered="false">
            <apex:outputText value="{!wrapper.ident}" rendered="false"/>
         </apex:column>
         
         <apex:column headerValue="Name" style="width:175px" >
            <apex:inputField value="{!wrapper.dep.Name}"/>
         </apex:column>
         
         <apex:column headerValue="Birth Year" style="width:100px" >
            <apex:inputField value="{!wrapper.dep.Birth_Year__c}" style="width:100px" />
         </apex:column>
         
         <apex:column headerValue="Gender" style="width:100px" >
            <apex:inputField value="{!wrapper.dep.Gender__c}"/>
         </apex:column>
         
         <apex:column headerValue="Relationship / Medical Issues" style="width:200px" >
            <apex:inputField value="{!wrapper.dep.Description__c}" style="width:200px" />
         </apex:column>
           
         <apex:column headerValue="Clothing Size" style="width:100px" >
            <apex:inputField value="{!wrapper.dep.Clothing_Size__c}" style="width:100px" />
         </apex:column>
         
         <apex:column headerValue="Shoe Size" style="width:100px" >
            <apex:inputField value="{!wrapper.dep.Shoe_Size__c}" style="width:100px" />
         </apex:column>
         
         <apex:column headerValue="Diaper Size" style="width:100px" >
            <apex:inputField value="{!wrapper.dep.Diaper_Size__c}" style="width:100px" />
         </apex:column>
         
         <apex:column headerValue="Breast-feed?" style="width:75px" >
            <apex:inputField value="{!wrapper.dep.Feeding__c}"/>
         </apex:column>
         
         <apex:column headerValue="Formula Type" style="width:100px" >
            <apex:inputField value="{!wrapper.dep.Formula_Type__c}" style="width:100px" />
         </apex:column>
         
         <apex:column headerValue="Medically Fragile" style="width:100px" >
            <apex:inputField value="{!wrapper.dep.Medically_Fragile__c}"/>
         </apex:column>
 
      </apex:pageBlockTable>
      <apex:outputText >Add one child or family member at a time, then click 'Add Row' to continue adding additional children or family members.</apex:outputText>
      <apex:commandButton value="Add Row" action="{!addRows}" rerender="wtable">
         <apex:param name="addCount" value="1" assignTo="{!addCount}"/> 
      </apex:commandButton>
      
   </apex:pageBlockSection>   
    
    <div align="center" draggable="false" >
      <apex:outputText ><b> We are a non-profit that believes in providing quality items to the people we serve.  We may not have the items you request but we will do our best. </b></apex:outputText>
      <br></br>
      <br></br>
      <apex:commandButton value="Save" action="{!save}"/>
    </div>

</apex:pageblock>
</apex:form>
</apex:page>
Benjamin OliverBenjamin Oliver

Hello Community,

Any thoughts?  The logic seems correct to me - but I am new and perhaps there is something I am not accounting for.  Any help would be appreciated!  

Thank you!