I have three Objects, Package_Item__c ,Product__c, Package__c.

Package_Item__c fields - Name, Quantity__c, Product__c(lookup to Product__c), Package__c(Lookup to Package__c)

Product__c fields - Name

Package__c fields - Name

I have a VF Datatable, that takes input of the Package_Item__c Quantity fields - as follows

<apex:page controller="CustomCnt">
<apex:inputField label="Name" value="{!pkg.Name}"/>
<apex:dataTable value="{!packageItems}" var="pkg1">
                <apex:inputField value="{!pkg1.Quantity__c}"/>

                    <apex:outputText value="{!pkg1.Product__r.Name}"/>
<apex:commandButton action="{!saveAll}" value="Save"/>
                <apex:commandButton value="Cancel"/>

My Requirements - The values entered in the Datatable, should be saved as a new Package_Item__c record with the Product__c Lookup field set to the one displayed on the outputtext, upon clicking the 'Save' button.

For eg - If The Quantity__c value Entered as '2', corresponding to the outputtext 'Apples' , the Package_Item__c record saved should be Name = Apples, Quantity = 2, Package = Value of Inputfield labelled 'Name'

Here is what I have tried

public with sharing class CustomCnt
public Package_Item__c[] packageItems {get; set;}
public Package__c pkg {get; set;}

public CustomCnt()
pkg = new Package__c();
public void saveAll()
        for(Package_Item__c p : packageItems)
            pkgitem1 = new Package_Item__c(Name = p.Product__r.Name, Quantity__c = p.Quantity__c, Package__c = pkg.Package__r.Name);
            insert pkgitem1;

I am getting an error as - "Variable does not exist: Package__r", on the above code.


As far as I can tell, pkg.Package__r.Name should be pkg.Id.

A lookup field, in Apex, is always set by Id, not by name. Further, your code is trying to say that Package__c.Package__r.Name, which suggests that the package has a parent package, which I'm pretty sure that's not what you're trying to do.

pkgitem1 = new Package_Item__c(Name = p.Product__r.Name, Quantity__c = p.Quantity__c, Package__c = pkg.Id);

Also, you should not be inserting records in a loop. Add all the records to a list, then insert them all at once.

Package_Item__c[] items = new Package_Item__c[0];
for(Package_Item__c p : packageItems) {
    items.add(new Package_Item__c(Name = p.Product__r.Name, Quantity__c = p.Quantity__c, Package__c = pkg.Id));
insert items;

Finally, you can insert the reords directly from packageItems, you don't need the interim step of copying the records.

for(Package_Item__c p : packageItems) {
    p.Name = p.Product__r.Name;
    p.Package__c = pkg.Id;
insert packageItems;

There's a few other bugs here, too, but I presume it's simply missing code from this question (e.g. you never insert pkg, so it's not a record). You may have more work to do.

  • Thanks this worked. Yes actually I did insert pkg, just didnt post the code here. Also could you explain how is the third solution working? As I see that you're setting the fields to the loop variable, but inserting packageItems.
    – An Amateur
    Dec 14 '20 at 16:35
  • @AnAmateur I suggest you read this and this, as they go in to more detail about this behavior, but basically, the loop variable p is a reference/alias to packageItems[i] (where i would be the current index of the loop), so we can modify the items in the list directly instead of creating a copy. This is often more efficient and what we intend to do.
    – sfdcfox
    Dec 14 '20 at 17:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.