0

I would appreciate some best practice advice here -

I have an insert trigger to populate a field in the record being inserted into a custom object with the value of a field in the parent object.

From other posts I learned that trigger.new cannot see any related fields.

Taking the value from a formula field on my custom object would normally be a choice but maximum number of object references has been reached due to high number of formula fields so I can't create another.

So I need to look up the value with SOQL and store it in a map with the Id of the record being inserted.

Which means that my before insert trigger must now be an after insert in order to know the Id.

If I query into a map and then update the field on the record being inserted I then need to issue an update DML statement, so in order to populate my field I need an insert and an update.

Seems inefficient - is that the only way?

Thanks, Mike.

2
  • 1
    Did you try implementing this feature using a workflow instead of developping a trigger? Commented Aug 5, 2015 at 8:57
  • Since "parent" can be used in many ways, is this a M-D relationship? If so, can there be more than one child? Is there a unique identifier in the new record (e.g Name or account) that one could use as a map key? If so, this could still be done in a before trigger context. With multiple children of a parent, can be hazardous to attempt without a unique identifier in a before trigger context.
    – crmprogdev
    Commented Aug 6, 2015 at 17:13

4 Answers 4

4

Actually you don't need to do that first insert to get the object's id. You need the id of the parent to do the query, and you should have that since it should be populated in the look-up field. I would do something like this:

// use a before insert trigger
// loop through trigger new, putting parent ids into a set<Id>
// query for parent objects, then use that list as argument in map constructor
// loop through trigger new again, get parent object from map, set field value

Update

I wanted to add a working example here to better illustrate my answer above. Note that if you are working with a look-up relationship, you should check to make sure that there actually is a parent record before trying to get a value from it.

trigger Contact on Contact (before insert){

    if (trigger.isBefore){
        if (trigger.isInsert){
            SetContactField.setAccountName(trigger.new);
        }
    }

}

public class SetContactField{

    public static void setAccountName(list<Contact> TriggerNew){

        list<Id> AccountIds = new list<Id>();

        for (Contact c : TriggerNew){
            AccountIds.add(c.AccountId);
        }

        map<Id,Account> RelatedAccounts = new map<Id,Account>([SELECT Id, Name FROM Account WHERE Id IN :AccountIds]);

        for (Contact c : TriggerNew){
            Account RelatedAccount = RelatedAccounts.get(c.AccountId);
            if (RelatedAccount == NULL){  // In a master detail relationship, this record is guaranteed to exist. 
                c.AccountName__c = NULL;
            } else {
                c.AccountName__c = RelatedAccount.Name;
            }
        }

    }

}
1
  • You've assumed a M-D detail relationship here. Not all child records are in a M-D relationship. An object can simply be used as a child without being linked in a M-D relationship, making it a related object instead that works as a child. One has to be careful here in answering questions in SF.SE because not everyone uses parent child the same. It doesn't always infer a M-D relationship. Doesn't mean one can't do essentially the same thing by other means though.
    – crmprogdev
    Commented Aug 6, 2015 at 17:07
0

You have at least a few options:

  1. Implement the trigger logic as described by martin, which queries the related object and build a Map object that you can use to pull in the reference values.
  2. Create a formula field that simply displays the value from the related object. For example, on the Contact object you could create a field named AccountName__c which simply has the formula Account.Name. Use a before insert and/or before update trigger to fill in the other field.
  3. Create a formula field (as described above) and use a workflow rule (no Apex!) to populate the target field.

For one of my projects where similar requirements were prevalent across multiple objects and use cases, I created a VLOOKUP "engine" that uses the same logic martin described. The engine uses custom settings to allow admins to declaratively define how to populate one field by looking up a related record, based on a value in a different field.

0

I had the same requirement and I accomplished it by URL hacking. Here you go:

{!URLFOR( $Action.IRR_s__c.New , null,
   [saveURL=Project_Product__c.Link, retURL=Project_Product__c.Link,CF00Ne0000001Wxuz=
      Project_Product__c.Name,CF00Ni000000CCLDX=Project_Product__c.Country__c,CF00Ne0000001X0pY=
         Project_Product__c.Country__c ])}

IRR_s__c is child object, Project_Product__c is parent object Project_Product__c.Name and Project_Product__c.Country__c are the fields that you want to populate in the child object.

You got to create a custom button and add it to the page layout.

1
  • This only works on a record by record basis while a trigger works for many records at a time. It also doesn't help when data is inserted using data loader or other means. Consequently, I'm not certain you've answered his question. Also, Salesforce is closing many URL hacks. These hacks may not work at all in a SF1 mobile app.
    – crmprogdev
    Commented Aug 6, 2015 at 16:55
0

Try implement something like below in a before insert trigger

// get the Id list
Set<Id> jobIds = new Set<Id>();
for(application__c app: (list<application__c>)Trigger.new){
    jobIds.add(app.job__c);
}

// SOQL the parent records
Map<Id, job__c> jobs = new Map<Id, job__c>([select id, jobStatus from job__c where id in: jobIds]);

for(application__c app: (list<application__c>)Trigger.new){
    job__c job = jobs.get(app.job__c);
    // update the child records value from parent
    app.jobStatus = job.jobStatus ; 
}

You must log in to answer this question.

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