1

I started writing a Trigger, which should, when the Status of a task is set to "completed", copy a custom field over to my contact.

Here is my code:

trigger taskTrigger on Task (after insert) {

    triggerHelper.copyField(trigger.new);

}

public with sharing class triggerHelper{

    public static void copyField(LIST<task> triggerNew) {

        LIST<Contact> toUpdate = new LIST<Contact>();

        for (task t:triggerNew){
            if (t.Status = 'Completed') {

            for (Contact c :[SELECT Id FROM Contact WHERE Id = t.Who]){
                toUpdate.Id = c.Id;
                toUpdate.customField = t.customField;
            }


            }

        }

    }

}

I am new to this, and I know it's not quite right. Can anyone help please? Tia.

4 Answers 4

2

You wrote good code following the guidelines for critical stuff; what you're missing now is some bit here and there.

So:

1 - The Trigger.New variable is a List, not a single record. You have to collect all the "WhoId" values from the Task included in the Trigger Context (i.e. one could update 2 tasks in the same run). To do so, create a Set< Id > and iterate over the Tasks in order to populate it, as a first step.

Set< Id > setOfId = new Set< Id >(); for (Task t: triggerNew) { setOfId.add(t.WhoId); }

2 - The loop for updating Contacts does not need to be within the loop iterating over Tasks. Split them in two separate loops (with the one which collects Task Contact Id first)

3 - You don't need to query Contacts if your intention is just to push data over them. Provided you have the Contact Id, you can an sObject instantiated by you instead of a SOQL generated one to pass over to DML (update) operation. Something like "contactToUpdate = new Contact(Id = '000XXX...', MyValue__c ='Ciao!')". So, simply make the for loop you already have iterate over the Set< Id > var you already collected, and remove the SOQL.

for (Id contactId: setOfId) { toUpdate.add(new Contact(Id = contactId, myField__c = myValue)); }

4 - After the line "toUpdate.customField = t.customField;", within the for loop block, add the record to the "toUpdate" list (probably you just forgot)

5 - Remember also to update the to update list at the very end of all this processing ;-)

1
  • (PS: WhoId could actually refer also to a Lead object since it's a multi-reference picklist. You should check for the first 3 chars of the Id to ensure the Task is attached to a Contact and not a Lead, when adding WhoId ids to the Set, to avoid issues later on).
    – MLucci
    Nov 6, 2014 at 13:55
1

Here is an implementation:

trigger taskTrigger on Task (after insert, after update) {
    Contact[] updates = new Contact[] {};
    for (Task t : Trigger.new) {
        if (t.WhoId != null
                && t.WhoId.getSObjectType() == Contact.SObjectType
                && t.Status == 'Completed') {
            updates.add(new Contact(Id = t.WhoId, CustomField__c = t.CustomField__c));
        }
    }
    update updates;
}

As tasks can be associated with any object (and used by many Salesforce apps) it makes sense to do as little work as possible when the task is not related to the object your trigger needs to work on. Being able to check the type of an ID without doing a query is good for this.

The other point to note is that you don't have to first query something to update it either.

0

Try the following code:

trigger taskTrigger on Task (after insert, after update) {
    TriggerHelper.copyField(trigger.new);
}


public with sharing class TriggerHelper {
    public static void copyField(List<Task> triggerNew) {

        Map<Task,Id> contactIdsByTasks = new Map<Task,Id>();
        for (task t : triggerNew) {
            if (t.Status == 'Completed') {
                contactIdsByTasks.put(t, t.Who);
            }
        }
        Map<Id,Contact> contactsToUpdateById = new Map<Id,Contact>([SELECT Id,customField FROM Contact WHERE Id IN: whoIds.values()]);
        for (Task t : triggerNew) {
            if (contactIdsByTasks.containsKey(t)) {
                Id contId = contactIdsByTasks.get(t);
                Contact tmpContact = contactsToUpdateById.get(contId);
                tmpContact.customField = t.customField;
                contactsToUpdateById.put(t.tmpContact);
            }
        }
        if ( !contactsToUpdateById.values().isEmpty()) {
            update contactsToUpdateById.values();
        }
    }
}
6
  • Thank you - I am trying this. When I try to save, I get an error for unexpected token for the line that contains Map<Id,Id> contactdsByTasks = Map<Id,Id>();
    – Lily
    Nov 6, 2014 at 14:14
  • @Lily i've updated the code Nov 6, 2014 at 14:19
  • Thank you! Now the problem seems to be that variable contId is not declared? Where do I declare this? I am sorry, these are stupid questions, but I am still learning.
    – Lily
    Nov 6, 2014 at 14:26
  • OK, I decared contId as follows: Id contId = contactIdsByTasks.get(t) , but now I have an incompatible key type for SOBJECT:Task for MAP
    – Lily
    Nov 6, 2014 at 14:30
  • @Lily see code again Nov 6, 2014 at 14:30
0

To write good code never put a SOQL query into a For loop. I have done a bit of tweaking to your code. Below, just check if I have closed all the '}'. It should work. I am trying to edit it to say map < something, its not working.

trigger taskTrigger on Task (after update) {
    triggerHelper.copyField(trigger.new);
}
public with sharing class triggerHelper{
    public static void copyField(LIST&lt;task&gt; triggerNew) {
        MAP&lt;ID, Contact&gt; toUpdate = new MAP&lt;ID, Contact&gt;([SELECT Id FROM Contact WHERE Id in: t.Who]]);
        for (task t:triggerNew){
            if (t.Status = 'Completed') {
  If(toUpdate.contains(t.whoid))              toUpdate.get(t.whoid).customField == t.customField;
          }
   }
update toUpdate.values();
}

Ninja Out.

1
  • @Sforce.Ninja For reference, <code> tags don't work on StackExchange sites! You can either indent everything by 4 spaces, or wrap single line code blocks with backticks (`). The easiest way is to just highlight the lot and hit the code {} button.
    – Matt Lacey
    Jan 5, 2017 at 23:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .