function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion

Please advise -- best method to add records in this VisualForce wizard

I'm creating a wizard using VisualForce / Apex, but having some trouble wrapping my head around the best method for doing it.
Here are the basics:
  • RMA__c (custom object) tracks the return of materials from customers (Return Material Authorization).  The object captures things like Customer name, RMA reason (hardware defect, product recall, product upgrade, invalid shipment, etc.), RMA request date, etc.  This object is a child in a Master-Detail relationship with the Case object.
  • RMA_Return__c (another custom object) tracks the individual line items of each material being returned: serial number, problem description / return reason, etc.  One field is a lookup to RMA__c (the parent RMA associated with this return).

In the first "page" of the wizard (not shown), we capture basic details (RMA return type, Customer, Case #).

Here's the second page of the wizard:

If that doesn't display well (it doesn't seem to be when I preview the post), click here.

I'm trying to add code to the "Add Card" link in that screenshot.  Clicking that link triggers the "addReturn" method in my Apex code, which is just a stub now.  The behavior that I want is:

Whenever the user clicks "Add Card", the wizard should go grab a new RMA_Return__c, then refresh this page so that there is an additional row of input boxes for the S/N and Problem Description fields. 

The number of RMA_Return__c records related to a RMA__c record is variable -- it's usually 1, but could be 2, 3 ... even dozens.  Because it's variable, I'm thinking I want to use a LIST of these RMA_Return__c records, but I'm not sure how I can display a varying number of these input fields on the refreshed page. 


public class newRmaController {
    public PageReference addReturn() {
        return null;

    Account vAccount;
    Case vCase;
    Switch__c vSwitch;
    RMA__c vRma;
    RMA_Return__c vReturn;
    public RMA_Return__c getRMA_Return() {
        if (vReturn == NULL) vReturn = new RMA_Return__c();
        return vReturn;

    public RMA__c getRma() {
        if (vRma == NULL) vRma = new RMA__c();
        return vRma;
    public Case getCase() {
        if (vCase == NULL) vCase = [SELECT id, casenumber, accountid, Switch__c, swrel__c
                                    FROM Case
                                    WHERE id = :System.currentPageReference().getParameters().get('cid')];
        return vCase;
    public Switch__c getSwitch() {
        if (vSwitch == NULL) vSwitch = [SELECT id, Last_SAT_Run__c, RMA_Contact__c, RMA_Phone__c, RMA_Street__c, RMA_City__c, RMA_State_Region__c, RMA_Zip_Code__c, RMA_Country__c
                                        FROM Switch__c
                                        WHERE id = :System.currentPageReference().getParameters().get('sid')];

        return vSwitch;
    public Hardware__c[] getC3HardwareList() {
        return [SELECT id, name, Product_Code__c
                FROM Hardware__c
                WHERE Switch__c = :System.currentPageReference().getParameters().get('sid')
                ORDER BY name];
    public PageReference step1() {
        return Page.CreateRma;

    public PageReference step2() {
        return Page.CreateRmaStep2Defect;



<!-- Create RMA Wizard: Step 2 for Defect / ECO Recall / Shipment Error RMA types -->
<apex:page controller="newRmaController" tabStyle="RMA__c">
  <apex:sectionHeader title="New RMA" subtitle="Step 2 : Select Returning Hardware"/>
  <apex:form >
    <apex:pageBlock title="RMA Detail" mode="edit">
      <apex:pageBlockButtons >
        <apex:commandButton action="{!step1}" value="Previous"/>
        <apex:commandButton action="{!step2}" value="Next"/>
      <apex:pageBlockSection title="RMA Information">
        <apex:inputField id="rmaType" value="{!Rma.Type__c}" required="TRUE"/>
        <apex:inputField id="caseNumber" value="{!Case.casenumber}" />
        <apex:inputField id="caseSwitch" value="{!Case.Switch__c}" required="TRUE"/>
        <apex:inputField id="caseAccount" value="{!Case.Accountid}" required="TRUE"/>

      <table width="100%"><tr valign="top">
         <td width="70%">
            <apex:pageBlockSection title="S/N of Returning Hardware" columns="2">
               <apex:inputField id="rtnSn" value="{!RMA_Return.SN__c}" />
               <apex:inputField id="rtnDescript" value="{!RMA_Return.Problem_Description__c}" styleClass="data2Col"/>
               <apex:commandLink action="{!addReturn}" value="Add Card"/>
         <td width="30%">
            <apex:pageBlockSection title="Installed HW as of Last SAT Audit">
            <apex:dataTable id="c3HardwareList" value="{!c3HardwareList}" var="hw" bgcolor="#F3F3EC"
             styleClass="list" rowClasses="dataRow" onRowMouseOver="hiOn(this);" onRowMouseOut="hiOff(this);">
             <apex:column >
                 <apex:facet name="header"><b>S/N</b></apex:facet>
                 <apex:outputLink value="/{!}">
             <apex:column >
                 <apex:facet name="header"><b>Product Code</b></apex:facet>
      <apex:pageBlockSection title="Ship-To Information : Verify with Customer for Accuracy" collapsible="TRUE" columns="2">
          <apex:inputField id="rmaContact" value="{!Switch.RMA_Contact__c}" />
          <apex:inputField id="rmaPhone" value="{!Switch.RMA_Phone__c}" />
          <apex:inputField id="rmaStreet" value="{!Switch.RMA_Street__c}" />
          <apex:inputField id="rmaCity" value="{!Switch.RMA_City__c}" />
          <apex:inputField id="rmaState" value="{!Switch.RMA_State_Region__c}" />
          <apex:inputField id="rmaZip" value="{!Switch.RMA_Zip_Code__c}" />
          <apex:inputField id="rmaCountry" value="{!Switch.RMA_Country__c}" />
      Display list of all installed hardware on this Switch</br>
      Provide input fields for users to enter S/N, Reason for Return

Anyone able to jump start my brain on this?

David VPDavid VP
You're almost there :

Just create a List<RMA_Return__c> returns = new List<RMA_Return__c>(); property in your controller
... and a RMA_Return__c currentreturn property. (don't forget the getters and setters)

In your addReturn() method you create a new RMA_Return__c() object, and point the currentreturn property of your controller to it

Create some input fields that bind to the currentreturn object. Add a save button that will add it to the list.

Your page can display a datatable that binds to the list. You could 'ajaxify' the whole thing with well chosen 'rerender' attributes ....

(a bit messy but I'm short on time - hope you get it)