You need to sign in to do that
Don't have an account?
Passing parent id to child record in VisualForce page
I'm attempting to create my first VF page. It is a line-item entry form that will allow a user to enter multiple child records (Lit_Order_Detail__c) before clicking save. Right now, I'm opening the VF page from a custom button on the parent (Lit_Order__c). However, when the page opens, the lookup field for the parent is not populated - so the user has to click the lookup to select the parent from Lit_Order__c. Is there a way to pass the parent id of the previous page to the new child records on the VF page?
My Visualforce page:
<apex:page standardController="Lit_Order_Detail__c" extensions="OrderEntry"> <apex:form > <apex:pageBlock title="Sales Literature Orders Quick Entry" > <apex:pageBlockButtons > <apex:commandButton value="Save" action="{!save}" rerender="error" /> </apex:pageBlockButtons> <apex:pageBlockTable value="{!ords}" var="a" id="table"> <apex:column headerValue="Order ID"> <apex:inputField value="{!a.Lit_Order__c}"/> </apex:column> <apex:column headerValue="Order Detail ID"> <apex:inputField value="{!a.Name}"/> </apex:column> <apex:column headerValue="Request"> <apex:inputField value="{!a.Literature_Request__c}"/> </apex:column> <apex:column headerValue="Quantity"> <apex:inputField value="{!a.Quantity__c}"/> </apex:column> </apex:pageBlockTable> <apex:pageblockButtons location="bottom"> <div style="text-align:right;margin-right:30px;font-weight:bold;"> <apex:commandLink value="Add Row" action="{!addRow}" rerender="table,error" immediate="true" /> | <apex:commandLink value="Remove Row" action="{!removeRow}" rerender="table,error" immediate="true" /> </div> </apex:pageblockButtons> </apex:pageBlock> </apex:form> </apex:page>
My Apex class:
public class OrderEntry { public List<Lit_Order_Detail__c> ords {get; set;} public OrderEntry(ApexPages.StandardController myController) { ords = new List<Lit_Order_Detail__c>(); ords.add(New Lit_Order_Detail__c());} public void addrow() { ords.add(new Lit_Order_Detail__c());} public void removerow(){ Integer i = ords.size(); ords.remove(i-1);} public PageReference save() { insert ords; PageReference home = new PageReference('/home/home.jsp'); home.setRedirect(true); return home; }}
Thank you!
Sorry about that, missed that part. I would say you don't even need to display the id of the parent, since the user won't be interested in seeing a 15 digit string anyway.
What you will need to do is to set it when you create the child object records in the custom controller.
<apex:page standardController="Lit_Order__c" extensions="OrderEntry"> <apex:form > <apex:pageBlock title="Sales Literature Orders Quick Entry" > <apex:pageBlockButtons > <apex:commandButton value="Save" action="{!save}" rerender="error" /> </apex:pageBlockButtons> <apex:pageBlockTable value="{!ords}" var="a" id="table"> <apex:column headerValue="Order Detail ID"> <apex:inputField value="{!a.Name}"/> </apex:column> <apex:column headerValue="Request"> <apex:inputField value="{!a.Literature_Request__c}"/> </apex:column> <apex:column headerValue="Quantity"> <apex:inputField value="{!a.Quantity__c}"/> </apex:column> </apex:pageBlockTable> <apex:pageblockButtons location="bottom"> <div style="text-align:right;margin-right:30px;font-weight:bold;"> <apex:commandLink value="Add Row" action="{!addRow}" rerender="table,error" immediate="true" /> | <apex:commandLink value="Remove Row" action="{!removeRow}" rerender="table,error" immediate="true" /> </div> </apex:pageblockButtons> </apex:pageBlock> </apex:form> </apex:page>
public class OrderEntry { public List<Lit_Order_Detail__c> ords {get; set;} private final Lit_Order__c parOrd; public OrderEntry(ApexPages.StandardController myController) { parOrd=(Lit_Order__c)myController.getrecord(); ords = new List<Lit_Order_Detail__c>(); Lit_Order_Detail__c LitOrd = new Lit_Order_Detail__c(); LitOrd.Lit_Order__c = parOrd.id; ords.add(LitOrd);} public void addrow() { Lit_Order_Detail__c LitOrd = new Lit_Order_Detail__c(); LitOrd.Lit_Order__c = parOrd.id; ords.add(LitOrd);} public void removerow(){ Integer i = ords.size(); ords.remove(i-1);} public PageReference save() { insert ords; PageReference home = new PageReference('/home/home.jsp'); home.setRedirect(true); return home; }}
Hopefully, this will get you close.
All Answers
I would suggest using the controller of the parent object as the stanard controller, then you can get the id automatically without passing it as a parameter.
<apex:page standardController="Lit_Order__c" extensions="OrderEntry"> <apex:form > <apex:pageBlock title="Sales Literature Orders Quick Entry" > <apex:pageBlockButtons > <apex:commandButton value="Save" action="{!save}" rerender="error" /> </apex:pageBlockButtons> <apex:pageBlockTable value="{!ords}" var="a" id="table"> <apex:column headerValue="Order ID"> <apex:inputField value="{!Lit_Order__c.id}"/> </apex:column> <apex:column headerValue="Order Detail ID"> <apex:inputField value="{!a.Name}"/> </apex:column> <apex:column headerValue="Request"> <apex:inputField value="{!a.Literature_Request__c}"/> </apex:column> <apex:column headerValue="Quantity"> <apex:inputField value="{!a.Quantity__c}"/> </apex:column> </apex:pageBlockTable> <apex:pageblockButtons location="bottom"> <div style="text-align:right;margin-right:30px;font-weight:bold;"> <apex:commandLink value="Add Row" action="{!addRow}" rerender="table,error" immediate="true" /> | <apex:commandLink value="Remove Row" action="{!removeRow}" rerender="table,error" immediate="true" /> </div> </apex:pageblockButtons> </apex:pageBlock> </apex:form> </apex:page>
if you need the parent in the controller (doesn't appear you do), you can use the getrecord call to pull it in. this would be good if you were doing any validation, or if you wanted to present some specific filtered data related to the parent.
public class OrderEntry { public List<Lit_Order_Detail__c> ords {get; set;} private final Lit_Order__c parOrd; public OrderEntry(ApexPages.StandardController myController) { parOrd=(Lit_Order__c)myController.getrecord(); ords = new List<Lit_Order_Detail__c>(); ords.add(New Lit_Order_Detail__c());} public void addrow() { ords.add(new Lit_Order_Detail__c());} public void removerow(){ Integer i = ords.size(); ords.remove(i-1);} public PageReference save() { insert ords; PageReference home = new PageReference('/home/home.jsp'); home.setRedirect(true); return home; }}
Thank you for your help. It's much closer, but I still have a problem: I get an error on save because the Lit_Order__c field is missing on the child records. Is there something else I need to do to actually set the value on the child records?
Thanks in advance - I realize that I'm probably asking pretty basic questions.
Partial VF page code (full code in previous posts):
<apex:pageBlockTable value="{!ords}" var="a" id="table"> <apex:column headerValue="Order ID"> <apex:inputField value="{!Lit_Order__c.id}"/> </apex:column> <apex:column headerValue="Order Detail ID"> <apex:inputField value="{!a.Name}"/> </apex:column> <apex:column headerValue="Request"> <apex:inputField value="{!a.Literature_Request__c}"/> </apex:column> <apex:column headerValue="Quantity"> <apex:inputField value="{!a.Quantity__c}"/> </apex:column> </apex:pageBlockTable>
Sorry about that, missed that part. I would say you don't even need to display the id of the parent, since the user won't be interested in seeing a 15 digit string anyway.
What you will need to do is to set it when you create the child object records in the custom controller.
<apex:page standardController="Lit_Order__c" extensions="OrderEntry"> <apex:form > <apex:pageBlock title="Sales Literature Orders Quick Entry" > <apex:pageBlockButtons > <apex:commandButton value="Save" action="{!save}" rerender="error" /> </apex:pageBlockButtons> <apex:pageBlockTable value="{!ords}" var="a" id="table"> <apex:column headerValue="Order Detail ID"> <apex:inputField value="{!a.Name}"/> </apex:column> <apex:column headerValue="Request"> <apex:inputField value="{!a.Literature_Request__c}"/> </apex:column> <apex:column headerValue="Quantity"> <apex:inputField value="{!a.Quantity__c}"/> </apex:column> </apex:pageBlockTable> <apex:pageblockButtons location="bottom"> <div style="text-align:right;margin-right:30px;font-weight:bold;"> <apex:commandLink value="Add Row" action="{!addRow}" rerender="table,error" immediate="true" /> | <apex:commandLink value="Remove Row" action="{!removeRow}" rerender="table,error" immediate="true" /> </div> </apex:pageblockButtons> </apex:pageBlock> </apex:form> </apex:page>
public class OrderEntry { public List<Lit_Order_Detail__c> ords {get; set;} private final Lit_Order__c parOrd; public OrderEntry(ApexPages.StandardController myController) { parOrd=(Lit_Order__c)myController.getrecord(); ords = new List<Lit_Order_Detail__c>(); Lit_Order_Detail__c LitOrd = new Lit_Order_Detail__c(); LitOrd.Lit_Order__c = parOrd.id; ords.add(LitOrd);} public void addrow() { Lit_Order_Detail__c LitOrd = new Lit_Order_Detail__c(); LitOrd.Lit_Order__c = parOrd.id; ords.add(LitOrd);} public void removerow(){ Integer i = ords.size(); ords.remove(i-1);} public PageReference save() { insert ords; PageReference home = new PageReference('/home/home.jsp'); home.setRedirect(true); return home; }}
Hopefully, this will get you close.
JIMRAE thanks for this, I adopted it to my own custom objects and was able to mod. One issue - on save, it brings me to the Home, not back to the record I wanted to add child records to.
Can you assist? thanks. To my beginner eyes it looks like the last section with return home in there but rewriting it is still challenge for me.
To get have the return bring you to the parent record, you modify your page reference to point back to the parent record id.
For the original example, it would look like this:
public class OrderEntry { public List<Lit_Order_Detail__c> ords {get; set;} private final Lit_Order__c parOrd; public OrderEntry(ApexPages.StandardController myController) { parOrd=(Lit_Order__c)myController.getrecord(); ords = new List<Lit_Order_Detail__c>(); Lit_Order_Detail__c LitOrd = new Lit_Order_Detail__c(); LitOrd.Lit_Order__c = parOrd.id; ords.add(LitOrd);} public void addrow() { Lit_Order_Detail__c LitOrd = new Lit_Order_Detail__c(); LitOrd.Lit_Order__c = parOrd.id; ords.add(LitOrd);} public void removerow(){ Integer i = ords.size(); ords.remove(i-1);} public PageReference save() { insert ords; //PageReference home = new PageReference('/home/home.jsp'); //home.setRedirect(true); //return home; }} PageReference parrec = new PageReference('/'+parOrd.id); parrec.setRedirect(true); return parrec; }}
You mean the whatid field, correct? Could you post your code?
Thanks for the help on the page return!
I figured out the issue on the VF pages for what ID and WhoID for tasks so am just cleaning up the appearance.
Is there a way I can have the row of entry fields have multiple rows?Since I want to make the page foradding multiple tasks the description/comments field is in display and it would be great to be able make it nice and wide, below the other shorter fields like subject, contact.
I am not sure if you could do that or not. One issue would be the column headers. The 2 iterators for records are the datatable and the pageblocktable, and they both use a one record per row model. You might be able to do it with custom styling, but I am not sure what you would do.
OK, thanks, you've been very helpful.
For now I am shaping the comments input with an inputTextarea that will just be narrower and longer down the page than usual.
Ah, one more question:
could i seta field value in the new task? I'd like for their status to be completed by default so they move into the history. ideally the status field won't even appear on the entry page. Will try a stab at it myself but am not quite sure where to begin... searching boards pulls up a lot of other topics
Regarding setting the status of the new tasks, that shouldn't be a problem. Actually, you should be able to set it when you construct the new Task in the controller.
public void addrow() { ords.add(new Task(Status='Completed'));}
For your refresh question, hard to tell. I would expect the behavior to be that the rows would get cleared out on the rerender (which happens when you add a new row). I would recommend training the users to add all of the rows they need first, then enter the data. Or, if that doesn't meet your design requirements you would need to modify your controller to capture the values in place before the new row is added and then populate them out again, I don't have any samples for this.
Thanks, I got the status passed ok.
Yeah, dunno about the clear out of comments. I hope that is something users will adapt to soon enough.
I am trying to change the page to have 3 rows of tasks by default instead of the "add row" feature b/c of the way adding a row clears out subject and description text but the controller is working funny.
any attempt to use a look up on the lower rows just feeds the info into the first row. Any suggestions would be appreciated. thanks.
Does anyone have a test class for this? I have been able to adapt the code to support multiple line enter for a new custom Opportunity Competitors object (junction object between Opportunity and new Competitors object ) but I can't seem to get the necessary coverage and keep getting an error in my test class - System.QueryException: List has no rows for assignment to SObject. I am very new to apex and would appreciate any guidance. Thanks in advance.
Page
Extension
Test
I would much rather just know how to test the already existing data that is out there. No need to take this topic off in a new direction. I can custom fit it to my standard. Later. Does anybody have a Testing Class for this as I am unsure how to test List Items.