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
brielea1984brielea1984 

Custom Save Button - Capture the Parent Id and route to new Visualforce Page for adding Multiple Children

Need to route the user to a visualforce page for creating multiple child records on save of parent record.

Summary
  • Three objects involved: Opportunity, Demographic, and Quota. 
  • One Opportunity has Many Demographics
  • One Demographic has Many Quotas
  • I've created a visualforce page where I add many Quotas to the Demographic at once. Currently this is launched from a custom button on the Demographic Detail Page.
    • Page Name = addQuotas
    • Page has a standard "add row"/"delete row" function to create a Quota record each row from custom controller
    • I pass multipe details from the parent Demographic onto each Quota row through an extension
  • I've created a visualforce page to override the standard new/edit Demographic layout so I can build a custom save button to route to the addQuotas page.
    • Page Name = addDemographic, uses a standard controller, no extensions at the moment
Question
What I want to have happen is when saving the Demographic, the user is immediately taken to the addQuotas page as if they had clicked the button on the detail page. I'm having difficulty making any of this work, trying custom buttons from the Opportunity and hacking the SaveURL, and I'm just not having luck saving the Demographic, grabbing the Id of that Demographic, and then going to the addQuotas page with that Demographic Id in tow. 

What do I add to the Save action on the addDemographic visualforce page to then route to the addQuotas page for THAT Demographic?

Basically, I want on Save of Demographic to automatically go here: /apex/addQuotas?id={!Demographic__c.Id}&retURL={!Demographic__c.Id}

Code and Pictures:
addDemographic page
<apex:page standardController="Demographic__c" tabStyle="Demographic__c">
     <apex:sectionHeader title="Edit Demographic" subtitle="New Demographic"/>
        <apex:form >
                <apex:pageBlock title="Edit Demograhic" mode="edit">
                    <apex:pageblockButtons >
                        <apex:commandButton action="{!save}" value="Add Quotas"/>
                    </apex:pageblockButtons>
                    <apex:pageblockSection title="Demographic Information" columns="1">
                        <apex:inputfield value="{!Demographic__c.Opportunity__c}"/>
                        <apex:inputfield value="{!Demographic__c.Qualification__c}"/>
                    </apex:pageblockSection> 
                </apex:pageBlock>
        </apex:form>

</apex:page>

addQuotas page:
<apex:page standardController="Demographic__c"
            extensions="EditableQuotaListExtension"
            showHeader="true" 
            sidebar="false"
            title="Edit Quota">
    <apex:form >
    <apex:pageMessages id="messages"/>
    <apex:pageBlock title="Edit Quotas">
      <apex:pageBlockButtons >
        <apex:commandButton value="Cancel" action="{!cancel}" />
        <apex:commandButton value="Save" action="{!save}"/>
      </apex:pageBlockButtons>
      <apex:pageBlockSection title="Demographic Information" collapsible="false">
      <apex:outputLink value="/{!Demographic__c.Id}" target="_blank">{!Demographic__c.Name}</apex:outputLink>
        <apex:pageBlockSectionItem >
          <apex:outputText value="{!Demographic__c.QualificationName__c}" />
          <apex:outputText value="{!Demographic__c.Qualification_Text__c}" />
        </apex:pageBlockSectionItem>
      </apex:pageBlockSection>
      <apex:pageBlockSection id="childList" columns="1" title="Quotas" collapsible="false">
        <apex:variable var="rowNum" value="{!ZERO}" />
        <apex:outputLabel value="No Quotas currently exist. Click below to Add." rendered="{!NOT(hasChildren)}"/>
        <apex:pageBlockTable value="{!children}" var="quota" rendered="{!hasChildren}">
        <apex:column headerValue="Condition">
          <apex:inputField value="{!quota.Condition__c}"/>
        </apex:column>
        <apex:column headerValue="Option">
          <apex:inputField value="{!quota.Condition_Option__c}"/>
        </apex:column>
        <apex:column headerValue="Description">
          <apex:inputField value="{!quota.Description__c}"/>
        </apex:column>
        <apex:column headerValue="Quota Amount">
          <apex:inputField value="{!quota.Quota_Amount__c}" />
        </apex:column>        
        <apex:column headerValue="%/#">
          <apex:inputField value="{!quota.Quota_Calculation_Type__c}"/>
        </apex:column>
        <apex:column headerValue="Demographic">
          <apex:inputField value="{!quota.Demographic__c}"/>
        </apex:column>
        <apex:column headerValue="Qualification">
          <apex:inputField value="{!quota.Qualification__c}"/>
        </apex:column>
          <apex:column headerValue=" ">
            <!-- This is the second half of the trick to keep track
                  of your row index for deletion. -->
            <apex:variable var="rowNum" value="{!rowNum + 1}" />
            <apex:commandLink value="Delete" action="{!removeFromList}" rerender="childList, messages" immediate="true">
              <apex:param name="removeIndex" assignTo="{!removeIndex}" value="{!rowNum}" />
            </apex:commandLink>
          </apex:column>
        </apex:pageBlockTable>
        <apex:commandButton value="Add Quota" action="{!addToList}" rerender="childList, messages" immediate="true" />
      </apex:pageBlockSection>
    </apex:pageBlock>
  </apex:form>
</apex:page>

addQuotas Extenstion (grabbing details from Demographic parent):
public with sharing class EditableQuotaListExtension extends EditableQuotaList
{


 public Demographic__c mydemo {get; private set;}

  public EditableQuotaListExtension(ApexPages.StandardController stdController) 
  {
    super(stdController);

    this.mydemo = [SELECT Id,
                              Name,
                                Qualification__r.Name
                            FROM Demographic__c
                            WHERE Id =: stdController.getRecord().Id];
    
    this.childList = [SELECT Id,
                          Condition__c,
                          Description__c,
                          Quota_Amount__c,
                          Quota_Calculation_Type__c,
                          Condition_Option__c,
                          Qualification__c,
                          Demographic__c
                      FROM Quota__c
                      WHERE Demographic__c =: mysObject.Id];
  }

  /*
   * This method is necessary for reference on the Visualforce page, 
   * in order to reference non-standard fields.
   */
  public List<Quota__c> getChildren()
  {
    return (List<Quota__c>)childList;
  }


  public override sObject initChildRecord()
  {
    Quota__c child = new Quota__c();
    child.Demographic__c = mydemo.Id;
    child.Qualification__c = mydemo.Qualification__c;
    child.Quota_Amount__c = 100;
    child.Quota_Calculation_Type__c = '%';
    
    return child;
  }
}

View of the addQuotas page so you get the idea of the page:
User-added image


Thank you in advance!!

 
Best Answer chosen by brielea1984
Terence_ChiuTerence_Chiu
If you add an extension class for the addDemographic VF page and use a custom save action and redirect to the addQuota page.
 
public class addDemographicExt{
   
   public Demographic__c dem {get; set;}


   public myControllerExtension(ApexPages.StandardController stdController) {

        dem= (Demographic__c)stdController.getRecord();
    }


    public PageReference saveDem(){
        try{
              upsert dem;
              
              PageReference pageRef = new PageReference('/apex/addQuotas?id=' + dem.Id + '&retUrl=' + dem.Id);
              pageRef.setRedirect(true);
              return pageRef;

        }catch(DMLException saveEx){
             //handle exception
        }

    }



}

You VF page would look something like the following:
 
<apex:page standardController="Demographic__c" tabStyle="Demographic__c" extension="addDemographicExt">
     <apex:sectionHeader title="Edit Demographic" subtitle="New Demographic"/>
        <apex:form >
                <apex:pageBlock title="Edit Demograhic" mode="edit">
                    <apex:pageblockButtons >
                        <apex:commandButton action="{!saveDem}" value="Add Quotas"/>
                    </apex:pageblockButtons>
                    <apex:pageblockSection title="Demographic Information" columns="1">
                        <apex:inputfield value="{!demOpportunity__c}"/>
                        <apex:inputfield value="{!dem.Qualification__c}"/>
                    </apex:pageblockSection> 
                </apex:pageBlock>
        </apex:form>

</apex:page>

 

All Answers

Terence_ChiuTerence_Chiu
If you add an extension class for the addDemographic VF page and use a custom save action and redirect to the addQuota page.
 
public class addDemographicExt{
   
   public Demographic__c dem {get; set;}


   public myControllerExtension(ApexPages.StandardController stdController) {

        dem= (Demographic__c)stdController.getRecord();
    }


    public PageReference saveDem(){
        try{
              upsert dem;
              
              PageReference pageRef = new PageReference('/apex/addQuotas?id=' + dem.Id + '&retUrl=' + dem.Id);
              pageRef.setRedirect(true);
              return pageRef;

        }catch(DMLException saveEx){
             //handle exception
        }

    }



}

You VF page would look something like the following:
 
<apex:page standardController="Demographic__c" tabStyle="Demographic__c" extension="addDemographicExt">
     <apex:sectionHeader title="Edit Demographic" subtitle="New Demographic"/>
        <apex:form >
                <apex:pageBlock title="Edit Demograhic" mode="edit">
                    <apex:pageblockButtons >
                        <apex:commandButton action="{!saveDem}" value="Add Quotas"/>
                    </apex:pageblockButtons>
                    <apex:pageblockSection title="Demographic Information" columns="1">
                        <apex:inputfield value="{!demOpportunity__c}"/>
                        <apex:inputfield value="{!dem.Qualification__c}"/>
                    </apex:pageblockSection> 
                </apex:pageBlock>
        </apex:form>

</apex:page>

 
This was selected as the best answer
Terence_ChiuTerence_Chiu
The constructor method name should be public addDemographicExt(ApexPages.StandardController stdController) {

Sorry about that.
brielea1984brielea1984
That worked fantastically!! Thank you so much; however, it looks like it created another issue. When I save a Quota on the next page I get the following error:

Visualforce Error
Formula Expression is required on the action attributes.

I'm assuming something I need to add to the extension for the addQuotas?
Terence_ChiuTerence_Chiu
You are using the standard save action, however, you are using the Demographic__c standard controller. You will need to build a custom save action to save the records.
 
public with sharing class EditableQuotaListExtension extends EditableQuotaList
{


 public Demographic__c mydemo {get; private set;}
 public List<Quota__c> children {get; set;}
  public EditableQuotaListExtension(ApexPages.StandardController stdController) 
  {
    super(stdController);

    this.mydemo = [SELECT Id,
                              Name,
                                Qualification__r.Name
                            FROM Demographic__c
                            WHERE Id =: stdController.getRecord().Id];
    
    this.childList = [SELECT Id,
                          Condition__c,
                          Description__c,
                          Quota_Amount__c,
                          Quota_Calculation_Type__c,
                          Condition_Option__c,
                          Qualification__c,
                          Demographic__c
                      FROM Quota__c
                      WHERE Demographic__c =: mysObject.Id];

     children = new List<Quota__c>();
     children.addALL(this.childList);
  }

  /*
   * This method is necessary for reference on the Visualforce page, 
   * in order to reference non-standard fields.
   */
  /*public List<Quota__c> getChildren()
  {
    return (List<Quota__c>)childList;
  }*/

  public PageReference saveChildren(){

      try{
           upsert children;
           //use the redirect method like the demographic page if needed after upsert
      }catch(DMLException saveEx){
         //do something
       }

       return null;
   }


  public override sObject initChildRecord()
  {
    Quota__c child = new Quota__c();
    child.Demographic__c = mydemo.Id;
    child.Qualification__c = mydemo.Qualification__c;
    child.Quota_Amount__c = 100;
    child.Quota_Calculation_Type__c = '%';
    
    return child;
  }
}

 
brielea1984brielea1984
Not yet, getting this error:
User-added image

I tried just removing that line, which allowed me to save, but then the controller didn't work in terms of adding any rows of record to the visualforce page. If it helps at all, here is the controller for the addquotas page.
 
public abstract with sharing class EditableQuotaList 
{
  // Used to help instantiate a counter for the Visualforce table rows
  public final Integer ZERO {get; private set;}

  public sObject mysObject {get; protected set;}
  public List<sObject> childList {get; set;}
  
  // Used for removing elements from the list
  public String removeIndex {get; set;}
  @TestVisible protected List<sObject> removeChildList {get;set;} 

  public EditableQuotaList()
  {
    this.ZERO = 0;
    this.removeChildList = new List<sObject>();

    // Implementing class can initialize this to retrieve existing
    // child records, OR this can be treated as a page where only new
    // items are added. If that is the case, then leave this as is.
    this.childList = new List<sObject>();
  }

  /*
   * Need to implement the following when implementing constructor:
   *
   *  - Query for child records, including all metadata to be shown on the page
   *    - Ensure query only returns the records associated with the parent
   *  - Set query results to childList List<sObject>
   */
    public EditableQuotaList(ApexPages.StandardController stdController) 
  {
    this();

    this.mysObject = (sObject)stdController.getRecord();
  }

  /*
   * Used to determine whether to display a message or the table
   */
  public Boolean getHasChildren()
  {
    return !childList.isEmpty();
  }

  /* 
   * Need to implement the following pseudocode
   *
   *  - Initialize child record
   *  - Set any default values
   *  - Set relationship with parent
   */
  public virtual sObject initChildRecord()
  {
    // Cannot instantiate a generic sObject, must choose an actual object
    // Since this class needs to be overridden, this is a placeholder
    // implementation.
    return new Quota__c();
  }

  /*
   * Used to add a new row to the table
   */
  public void addToList()
  {
    childList.add(initChildRecord());
  }

  /*
   * Used to remove a particular row from the table, referencing the
   * removeIndex that is set on the Visualforce page
   */
  public void removeFromList()
  {
    try
    {
      // removeIndex is one based
      Integer rowIndex = Integer.valueOf(removeIndex) - 1;
      
      if (childList.size() > rowIndex && rowIndex >= 0)
      {
        sObject sobj = childList.remove(rowIndex);
        
        // Need to delete it if it existed in the database
        if (sobj.Id != null)
        {       
          removeChildList.add(sobj);
        }
      }
    }
    catch (Exception e)
    {
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
    }
  }

  /*
   * Defines the Page that is returned upon a successful save
   */
  public virtual PageReference getSuccessURL()
  {
    PageReference pr;

    String retURL = ApexPages.currentPage().getParameters().get('retURL');
    // If retURL doesn't exist, simply return to parent record
    if (String.isBlank(retURL))
    {
      pr = new ApexPages.StandardController(mysObject).view();
    }
    else
    {
      pr = new PageReference(retURL);
    }
    
    pr.setRedirect(true);
    return pr;
  }

  /*
   * Persists the records saved in the table, or deletes existing records
   * that the user deleted in the table.
   */
  public PageReference save()
  {
    Savepoint sp = Database.setSavepoint();
            
    try
    {
      // DML Upsert isn't supported for List<sObject>, so we need to do
      // explicit separate insert and update
      List<sObject> insertChildList = new List<sObject>();
      List<sObject> updateChildList = new List<sObject>();
      for (sObject sobj : childList)
      {
        if (sobj.Id == null)
        {
          insertChildList.add(sobj);
        }
        else
        {
          updateChildList.add(sobj);
        }
      }

      insert insertChildList;
      update updateChildList;
      delete removeChildList;
      
      return getSuccessURL();
    }
    catch(Exception e)
    {
      Database.rollback(sp);
                
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
            
      return null;
    } 
  } 
}

thank you thank you thank you again
brielea1984brielea1984
Got it to work!!! I wasn't thinking and didn't see I needed to add {!saveChildren} as the action for the button rather than {!save}

Thank you so much!!!
SFDC9999SFDC9999
Hi , 
I am trying to do the same and i am stuck with the same error 

Compile Error: Incompatible argument type List<SObject> for All method on List<Issue_Line__c> at line 35 column 5

I am not able to fix this , Could you please let me know how you did this as i removed the visual force pagew where i has used action Saveand tried to save the controller and it still the class has not worked . 

Thanks 
 
SFDC9999SFDC9999
@brielea 1984 / @Terence_chiu

Stll could not resolve this . Any help on this error message please. So close

   children = new List<Issue_line__c>();
    children.addALL(this.childList);
Compile Error: Incompatible argument type List<SObject> for All method on List<Issue_Line__c>
brielea1984brielea1984
@SFDC9999 Can you post your entire code so I can evaluate?

My guess is that you need to replace List<Issue_Line__c> with the parent object rather than the child, but without looking at the whole thing it's hard to guess. Thanks!
brielea1984brielea1984
Also don't forget there are two pieces of code, there's the extension too which is what references the parent object.
SFDC9999SFDC9999
Hi , 

Thank you very very much for responding . If possible could you please look at this once. I have done exactly what was done above .

I tried changing that and it did not work. My parent object is case (Demographic__c) and child is issue line (Quote__c)
I have used the exact same code and I belive i have the same use case as you had with VF page for Parent and add mutiple child records
Parent VF (Case)
<apex:page standardController="Case" extensions="CC_CaseEdit">
     <apex:sectionHeader title="Case Edit" subtitle="{!Case.Casenumber}"/>
           <apex:form > 
                      <apex:pageBlock title="Case Edit" mode="edit">
                      
                           <apex:pageBlockButtons location="top"> 
                                 <apex:commandButton value="Save" action="{!SaveCase}"/>
                                 <apex:commandButton value="Save & New" action="{!save}" /> 
                                 <apex:commandButton value="Cancel" action="{!cancel}"/>
                           </apex:pageBlockButtons> 
                           
                         
                           <apex:pageBlockSection title="Case Information" columns="2"> 
                                <apex:inputField value="{!Case.OwnerId}" required="false"/>
                                <apex:inputField value="{!Case.CaseNumber}" required="false"/>
                                <apex:inputField value="{!Case.Status}" required="true"/>
                                <apex:inputField value="{!Case.Type}" required="false"/>
                                <apex:inputField value="{!Case.Priority}" required="false"/>
                                <apex:inputField value="{!Case.Sub_Type__c}" required="false"/>
                                <apex:inputField value="{!Case.Origin}" required="true"/> 
                                <apex:inputField value="{!Case.Sub_Type_Detail__c}" required="false"/>
                               
                       </apex:pageBlockSection>
                       
             </apex:pageBlock>
      </apex:form>
</apex:page>
Parent Controller
public class CC_CaseEdit{
   
   public Case dem {get; set;}


   public CC_CaseEdit(ApexPages.StandardController stdController) {

        dem= (case)stdController.getRecord();
    }


    public PageReference savecase(){
       
              upsert dem;
              
              PageReference pageRef = new PageReference('/apex/AddEdit_Multiple_Issue_Lines?id=' + dem.Id + '&retUrl=' + dem.Id);
              pageRef.setRedirect(true);
             

       
        return pageRef;
       
         
    }
    }
Child VF ( Add mutiple child records Issue )
<apex:page standardController="Case"
            extensions="CC_Editable_IssueLine_ListExtension"
            showHeader="true" 
            sidebar="false"
            title="Add/Edit Issue Lines">
    <apex:form >
    <apex:pageMessages id="messages"/>
    <apex:pageBlock title="Add/Edit Issue Lines">
      <apex:pageBlockButtons >
        
         <apex:commandButton value="Save" action="{!saveChildren}"/>
          <apex:commandButton value="Cancel" action="{!cancel}" />
      </apex:pageBlockButtons>
      <apex:pageBlockSection title="Issue Information" collapsible="false">
        <apex:pageBlockSectionItem >
             <apex:outputText value="Issue Number" />
             <apex:outputLink value="/{!Case.Id}" target="_blank">{!Case.CaseNumber}</apex:outputLink>
        </apex:pageBlockSectionItem>
        <apex:pageBlockSectionItem >
             <Apex:outputLabel >Issue Type</Apex:outputLabel>
             <apex:outputfield value="{!Case.Type}" />
        </apex:pageBlockSectionItem> 
        <apex:pageBlockSectionItem >
             <Apex:outputLabel >Issue Account</Apex:outputLabel>
             <apex:outputfield value="{!Case.Account.Name}" />
        </apex:pageBlockSectionItem>  
        <apex:pageBlockSectionItem >
             <Apex:outputLabel >Issue Status</Apex:outputLabel>
             <apex:outputfield value="{!Case.status}" />
        </apex:pageBlockSectionItem>   
        
        <!-- Add additional parent fields here -->
      </apex:pageBlockSection>
      <apex:pageBlockSection id="childList" columns="1" title="Issue Lines" collapsible="false">
        <!-- There is a trick to creating a counter when rendering rows in a
              pageBlockTable. You have to define a variable to default to 0,
              and then update that variable inside the table row. This is the
              way that I can leverage smart row deletes -->
        <apex:variable var="rowNum" value="{!ZERO}" />
        <apex:outputLabel value="No Issue lines currently exist. Click below to Add." rendered="{!NOT(hasChildren)}"/>
        <apex:pageBlockTable value="{!children}" var="Issue_Line__c" rendered="{!hasChildren}">
        
          <apex:column headerValue="Product">
            <apex:inputField value="{!Issue_Line__c.Product__c}" />
          </apex:column>
          <apex:column headerValue="Quantity">
            <apex:inputField value="{!Issue_Line__c.Quantity__c}" />
          </apex:column>
          <apex:column headerValue="Actual Quantity">
            <apex:inputField value="{!Issue_Line__c.Actual_Quantity__c}" />
          </apex:column>
          <apex:column headerValue="Pallet Sequence #">
            <apex:inputField value="{!Issue_Line__c.Pallet_Sequence__c}" />
          </apex:column>
          <apex:column headerValue="Reason">
            <apex:inputField value="{!Issue_Line__c.Reason__c}" />
          </apex:column>
          <!-- Add additional children metadata columns here -->
          <apex:column headerValue=" ">
            <!-- This is the second half of the trick to keep track
                  of your row index for deletion. -->
            <apex:variable var="rowNum" value="{!rowNum + 1}" />
            <apex:commandLink value="Delete" action="{!removeFromList}" rerender="childList, messages" immediate="true">
              <apex:param name="removeIndex" assignTo="{!removeIndex}" value="{!rowNum}" />
            </apex:commandLink>
          </apex:column>
        </apex:pageBlockTable>
        <!-- Want to specify immediate here and above so validation does
              not occur when you are trying to add/remove rows. Only want
              validation to occur when trying to save -->
        <apex:commandButton value="Add Issue Line" action="{!addToList}" rerender="childList, messages" immediate="true" />
      </apex:pageBlockSection>
    </apex:pageBlock>
  </apex:form>
</apex:page>

Child Controller 
public abstract with sharing class CC_EditableList 
{
  // Used to help instantiate a counter for the Visualforce table rows
  public final Integer ZERO {get; private set;}

  public sObject mysObject {get; protected set;}
  public List<sObject> childList {get; set;}
  
  // Used for removing elements from the list
  public String removeIndex {get; set;}
  @TestVisible protected List<sObject> removeChildList {get;set;} 

  public CC_EditableList()
  {
    this.ZERO = 0;
    this.removeChildList = new List<sObject>();


    this.childList = new List<sObject>();
  }


  public CC_EditableList(ApexPages.StandardController stdController) 
  {
    this();

    this.mysObject = (sObject)stdController.getRecord();
  }

  /*
   * Used to determine whether to display a message or the table
   */
  public Boolean getHasChildren()
  {
    return !childList.isEmpty();
  }

 
  public virtual sObject initChildRecord()
  {
 
    return new Issue_line__c();
  }

  /*
   * Used to add a new row to the table
   */
  public void addToList()
  {
    childList.add(initChildRecord());
  }

  /*
   * Used to remove a particular row from the table, referencing the
   * removeIndex that is set on the Visualforce page
   */
  public void removeFromList()
  {
    try
    {
      // removeIndex is one based
      Integer rowIndex = Integer.valueOf(removeIndex) - 1;
      
      if (childList.size() > rowIndex && rowIndex >= 0)
      {
        sObject sobj = childList.remove(rowIndex);
        
        // Need to delete it if it existed in the database
        if (sobj.Id != null)
        {       
          removeChildList.add(sobj);
        }
      }
    }
    catch (Exception e)
    {
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
    }
  }

  /*
   * Defines the Page that is returned upon a successful save
   */
  public virtual PageReference getSuccessURL()
  {
    PageReference pr;

    String retURL = ApexPages.currentPage().getParameters().get('retURL');
    // If retURL doesn't exist, simply return to parent record
    if (String.isBlank(retURL))
    {
      pr = new ApexPages.StandardController(mysObject).view();
    }
    else
    {
      pr = new PageReference(retURL);
    }
    
    pr.setRedirect(true);
    return pr;
  }


  public PageReference save()
  {
    Savepoint sp = Database.setSavepoint();
            
    try
    {
      // DML Upsert isn't supported for List<sObject>, so we need to do
      // explicit separate insert and update
      List<sObject> insertChildList = new List<sObject>();
      List<sObject> updateChildList = new List<sObject>();
      for (sObject sobj : childList)
      {
        if (sobj.Id == null)
        {
          insertChildList.add(sobj);
        }
        else
        {
          updateChildList.add(sobj);
        }
      }

      insert insertChildList;
      update updateChildList;
      delete removeChildList;
      
      return getSuccessURL();
    }
    catch(Exception e)
    {
      Database.rollback(sp);
                
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
            
      return null;
    } 
  } 
}

Child Controller Extension : In this i had the error same as you did Incompatible argument type List<SObject> for All method on List<Issue_Line__c>
public with sharing class CC_Editable_IssueLine_ListExtension extends CC_EditableList
{


 public Case mydemo {get; private set;}
 public List<Issue_line__c> children {get; set;}
  public CC_Editable_IssueLine_ListExtension(ApexPages.StandardController stdController) 
  {
    super(stdController);

    this.mydemo = [SELECT Id,
                              CaseNumber,
                               Type
                            FROM Case
                            WHERE Id =: stdController.getRecord().Id];
    
    this.childList = [SELECT Id,
                         Quantity__c,
                          Pallet_Sequence__c,
                          Warranty_Line_Number__c,
                          Actual_Quantity__c,
                          Case__c,
                          Issue_Line_External_Id__c,
                          Product__c,
                          Product_Type__c,
                          Reason__c,
                          Return_Size__c,
                          Type_of_Defect__c,
                          Total_Weight__c
                       
                      FROM Issue_line__c
                      WHERE Case__c =: mysObject.Id];

   Children= new List<Issue_line__c>();
  //  children.addALL(this.childList);
  }

  /*
   * This method is necessary for reference on the Visualforce page, 
   * in order to reference non-standard fields.
   */
 public List<Issue_line__c> getChildren()
  {
    return (List<Issue_line__c>)childList;
  }

  public PageReference saveChildren(){

      try{
           upsert children;
           //use the redirect method like the demographic page if needed after upsert
      }catch(DMLException saveEx){
         //do something
       }

       return null;
   }


  public override sObject initChildRecord()
  {
    Issue_line__c child = new Issue_line__c();
    child.Case__c = mydemo.Id;
  
    
    return child;
  }
}

Sorry for the long list of codes
brielea1984brielea1984
No problem, it's been over a year since this use case so I'm trying to refresh my own memory of what was going on. I actually found my final code on this tucked away as there were changes after this issue. I do see an issue in that you have <b> tags on line 34 and 35. Also line 35 is commented out. That being said, in my finished code, those lines aren't even in there anymore.  Also note that in the saveChildren method (line 46) you need a pagereference to direct the system as to what page you go to next. Try comparing your code to this: 
 
public abstract with sharing class EditableQuotaList   
 {  
   // Used to help instantiate a counter for the Visualforce table rows  
   public final Integer ZERO {get; private set;}  
   
   public sObject mysObject {get; protected set;}  
   public List<sObject> childList {get; set;}  
     
   // Used for removing elements from the list  
   public String removeIndex {get; set;}  
   @TestVisible protected List<sObject> removeChildList {get;set;}   
   
   public EditableQuotaList()  
   {  
     this.ZERO = 0;  
     this.removeChildList = new List<sObject>();  
   
     // Implementing class can initialize this to retrieve existing  
     // child records, OR this can be treated as a page where only new  
     // items are added. If that is the case, then leave this as is.  
     this.childList = new List<sObject>();  
   }  
   
   /* 
    * Need to implement the following when implementing constructor: 
    * 
    *  - Query for child records, including all metadata to be shown on the page 
    *    - Ensure query only returns the records associated with the parent 
    *  - Set query results to childList List<sObject> 
    */  
     public EditableQuotaList(ApexPages.StandardController stdController)   
   {  
     this();  
   
     this.mysObject = (sObject)stdController.getRecord();  
   }  
   
   /* 
    * Used to determine whether to display a message or the table 
    */  
   public Boolean getHasChildren()  
   {  
     return !childList.isEmpty();  
   }  
   
   /*  
    * Need to implement the following pseudocode 
    * 
    *  - Initialize child record 
    *  - Set any default values 
    *  - Set relationship with parent 
    */  
   public virtual sObject initChildRecord()  
   {  
     // Cannot instantiate a generic sObject, must choose an actual object  
     // Since this class needs to be overridden, this is a placeholder  
     // implementation.  
     return new Quota__c();  
   }  
   
   /* 
    * Used to add a new row to the table 
    */  
   public void addToList()  
   {  
     childList.add(initChildRecord());  
   }  
   
   /* 
    * Used to remove a particular row from the table, referencing the 
    * removeIndex that is set on the Visualforce page 
    */  
   public void removeFromList()  
   {  
     try  
     {  
       // removeIndex is one based  
       Integer rowIndex = Integer.valueOf(removeIndex) - 1;  
         
       if (childList.size() > rowIndex && rowIndex >= 0)  
       {  
         sObject sobj = childList.remove(rowIndex);  
           
         // Need to delete it if it existed in the database  
         if (sobj.Id != null)  
         {         
           removeChildList.add(sobj);  
         }  
       }  
     }  
     catch (Exception e)  
     {  
       ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));  
     }  
   }  
   
   /* 
    * Defines the Page that is returned upon a successful save 
    */  
   public virtual PageReference getSuccessURL()  
   {  
     PageReference pr;  
   
     String retURL = ApexPages.currentPage().getParameters().get('retURL');  
     // If retURL doesn't exist, simply return to parent record  
     if (String.isBlank(retURL))  
     {  
       pr = new ApexPages.StandardController(mysObject).view();  
     }  
     else  
     {  
       pr = new PageReference(retURL);  
     }  
       
     pr.setRedirect(true);  
     return pr;  
   }  
   
   /* 
    * Persists the records saved in the table, or deletes existing records 
    * that the user deleted in the table. 
    */  
   public PageReference save()  
   {  
     Savepoint sp = Database.setSavepoint();  
               
     try  
     {  
       // DML Upsert isn't supported for List<sObject>, so we need to do  
       // explicit separate insert and update  
       List<sObject> insertChildList = new List<sObject>();  
       List<sObject> updateChildList = new List<sObject>();  
       for (sObject sobj : childList)  
       {  
         if (sobj.Id == null)  
         {  
           insertChildList.add(sobj);  
         }  
         else  
         {  
           updateChildList.add(sobj);  
         }  
       }  
   
       insert insertChildList;  
       update updateChildList;  
       delete removeChildList;  
         
       return getSuccessURL();  
     }  
     catch(Exception e)  
     {  
       Database.rollback(sp);  
                   
       ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));  
               
       return null;  
     }   
   }   
 }

And
 
public with sharing class EditableQuotaListExtension extends EditableQuotaList  
  {  
    
    
   public Demographic__c mydemo {get; private set;}  
    
    public EditableQuotaListExtension(ApexPages.StandardController stdController)   
    {  
      super(stdController);  
    
      this.mydemo = [SELECT Id,  
                                Name,  
                                Opportunity__r.Id,  
                                  Qualification__r.Name  
                              FROM Demographic__c  
                              WHERE Id =: stdController.getRecord().Id];  
        
      this.childList = [SELECT Id,  
                            Condition__c,  
                            Description__c,  
                            Quota_Amount__c,  
                            Quota_Calculation_Type__c,  
                            Condition_Option__c,  
                            Conditional_Option_Open__c,  
                            Qualification__c,  
                            Demographic__c  
                        FROM Quota__c  
                        WHERE Demographic__c =: mysObject.Id];  
    }  
    
    /* 
     * This method is necessary for reference on the Visualforce page,  
     * in order to reference non-standard fields. 
     */  
    public List<Quota__c> getChildren()  
    {  
      return (List<Quota__c>)childList;  
    }  
    
    
    public override sObject initChildRecord()  
    {  
      Quota__c child = new Quota__c();  
      child.Demographic__c = mydemo.Id;  
        
      return child;  
    }  
      
     public PageReference saveChildren(){  
    
        try{  
             upsert childList;  
                pageReference pageRef = new PageReference('/'+myDemo.Opportunity__r.Id);  
                pageRef.setRedirect(true);  
                return pageRef;  
    
        }catch(DMLException saveEx){  
           pageReference pageRef = new PageReference('/'+myDemo.Id);  
                pageRef.setRedirect(true);  
                return pageRef;  
         }  
    
         return null;  
     }  
      
  }

 
SFDC9999SFDC9999
I was able to top correct the misatke and it is working perfectly now .Thank you very much . I really appreacite it . 
Sylvie SerpletSylvie Serplet
Hi,
I try to implement the same code but face another problem. When my children records are saved they are created correctly but are empty.
Any thought before I post my codes?
Thank you in advance for your help.
Sylvie
SFDC9999SFDC9999
Hi Sylvie,

Not sure why it is that way. If you have used the above code it should not happen that way. It working perfectly for me . There might be a small thing you might have missed . Check it out and if you cant find it then post the code here .

Thanks
Sylvie SerpletSylvie Serplet
Hi,
 
One precision, I am working in Lightning, always wonder if it is not the reason why it is not working.
 
My configuration: 3 Objects: Opportunity (parent), Fact_Finder__c (child), FFDriver__c (grandchild). All with Master-Detail relationship.
On my Opportunity detail page I have a Lightning Component with several buttons which open VF Pages (Fact_Finder__c) with different record types.
 
My problem is when I save the DriverForm (doSave) the records are created (Fact Finder with all infos and Driver with only the one in  initChildRecord) but nothing that I put in other fields.
 User-added image
I have tried to simplify the code (taking out styles and many fields). Sorry it still very long….
 
VF PAGE (MotorForm) – child level
<apex:page standardcontroller="Fact_Finder__c" extensions="FFFormCtrExt" showHeader="false" sidebar="false" >

<apex:form style="width:800px; text-align:center; margin:auto;" enctype="multipart/form-data" > 
  <apex:pageMessages />
   <apex:pageBlock id="block" title="Motor Fact Finder" >        
       <apex:pageBlockButtons location="bottom" > 
            <apex:commandButton action="{!cancel}" value="Cancel" immediate="true" styleClass="buttoncancel" />
            <apex:commandButton action="{!addDriver}" value="Add Driver" styleclass="buttonsubmit" />
            <apex:commandButton action="{!saveFF}" value="Save-No Driver" styleclass="buttonsubmit" />
          </apex:pageBlockButtons> 
        <apex:outputPanel styleClass="black" layout="block">
              <apex:pageblocksection columns="1">                    
                    <apex:inputfield value="{!FF.Opportunity_Name__c}"/>            
                    <apex:inputfield value="{!FF.Client_Name__c}"/>
                    <apex:inputfield value="{!FF.Date__c}"/>
                    <apex:selectRadio value="{!FF.Attached_to__c}" styleclass="radioB" style="width:350px;" layout="pageDirection" > 
                       <apex:selectOption itemValue="Business Pack" itemlabel="Business Pack"  />
                       <apex:selectOption itemValue="Farm Pack" itemlabel="Farm Pack"/>
                    </apex:selectRadio>                    
          </apex:pageblocksection>  
     </apex:outputPanel>             
    <apex:outputPanel styleClass="black" layout="block">
        <apex:pageblocksection title="Client Details" showheader="true" collapsible="true" columns="1">                  
                    <apex:inputfield value="{!FF.Legal_Name__c}"/>
                    <apex:inputfield value="{!FF.Trading_as__c}"/>                    
                     <apex:inputfield value="{!FF.ABN__c}"/>
                    <apex:inputfield value="{!FF.ACN__c}"/>
             <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Address"/>
                    <apex:inputField value="{!FF.Street_Address__c}"/>
             </apex:pageBlockSectionItem>
                    <apex:inputfield value="{!FF.Phone__c}"/>
                    <apex:inputfield value="{!FF.Email__c}"/>
                    <apex:inputfield value="{!FF.Primary_Contact__c}"/>
                    <apex:inputfield value="{!FF.Date_of_Birth__c}"/>  
        </apex:pageblocksection>
…….
   </apex:outputPanel>             
     <apex:outputPanel styleClass="black" layout="block">
      <apex:pageblocksection title="Other Information" showheader="true" collapsible="true" columns="1">
                   <apex:actionSupport event="onchange" action="{!readUser}" />
               <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Prepared by"/>
                    <apex:inputField value="{!FF.Owner__c}"/>            
               </apex:pageBlockSectionItem>
                    <apex:inputfield value="{!FF.Notes__c}"/>
       </apex:pageblocksection>                 
     </apex:outputPanel>
     </apex:pageBlock>     
   </apex:form>         
</apex:page>

Extension (FFFormCtrExt)
public with sharing class FFFormCtrExt {

 public User selectedUser {get; set;}   
  public string CurrentPageName {get;set;}
  
  public Opportunity opp {get;set;}
  string recordId = ApexPages.currentPage().getParameters().get('recordId'); 
  public Fact_Finder__c FF {get; set;} 
  string FFId = ApexPages.currentPage().getParameters().get('FFId');    
     public FFFormCtrExt(ApexPages.StandardController controller) {         
       opp =  [SELECT Id, Name, ABN__c, ACN__c, Email__c, Phone__c, Address__c, Primary_Contact__c, Account.Name FROM Opportunity WHERE Id =:ApexPages.currentPage().getParameters().get('recordId')];         
       this.FF=(Fact_Finder__c)controller.getRecord();           
                               
       //All forms       
       FF.Opportunity_Name__c= recordId; 
       FF.ABN__c= opp.ABN__c;
       FF.ACN__c= opp.ACN__c;
       FF.Phone__c= opp.Phone__c;
       FF.Email__c= opp.Email__c;
       FF.Primary_Contact__c= opp.Primary_Contact__c;
       FF.Client_Name__c= opp.AccountId;
       FF.Street_Address__c= opp.Address__c;        
……     
       FF.recalculateFormulas();        
       FF.Owner__c = UserInfo.getUserId();
       selectedUser = [ Select Id From User Where Id = :UserInfo.getUserId()];          
        }               
    public pageReference readUser()   {
        selectedUser = [ Select Id From User Where Id = :FF.Owner__c ];
        return null;      
    }                 
   public PageReference addDriver()  {        
        FF.RecordTypeId= '01228000000U19O';    
        insert (This.FF);
        PageReference ref = new Pagereference('/apex/DriverForm');
        ref.getParameters().put('FFId', FF.Id);
        ref.getParameters().put('recordId', FF.Opportunity_Name__c);
        ref.setRedirect(true);
        return ref;
      }                            
    public PageReference cancel(){   
     return new PageReference('/' + recordId);   
    }    
    public PageReference saveFF() {       
       
     RecordType rt;             
        if(CurrentPageName == 'HomeForm')
            rt = [Select Id From RecordType Where DeveloperName = 'Home_Contents' And sObjectType = 'Fact_Finder__c'];
        if(CurrentPageName == 'MotorForm')
            rt = [Select Id From RecordType Where DeveloperName = 'Motor' And sObjectType = 'Fact_Finder__c'];
         if(CurrentPageName == 'BusinessForm')   
            rt = [Select Id From RecordType Where DeveloperName = 'Business_Package' And sObjectType = 'Fact_Finder__c'];
        if(CurrentPageName == 'ContractForm')   
            rt = [Select Id From RecordType Where DeveloperName = 'Contract_Works' And sObjectType = 'Fact_Finder__c'];
        if(CurrentPageName == 'FarmForm')   
            rt = [Select Id From RecordType Where DeveloperName = 'Farm' And sObjectType = 'Fact_Finder__c'];
        if(CurrentPageName == 'AccidentForm')   
            rt = [Select Id From RecordType Where DeveloperName = 'Accident_Illness' And sObjectType = 'Fact_Finder__c'];
        if(CurrentPageName == 'PIForm')   
            rt = [Select Id From RecordType Where DeveloperName = 'Professional_Indemnity' And sObjectType = 'Fact_Finder__c']; 
        if(CurrentPageName == 'GenericForm')   
            rt = [Select Id From RecordType Where DeveloperName = 'Generic' And sObjectType = 'Fact_Finder__c'];          
        FF.RecordTypeId = rt.Id;                         
        insert (this.FF);           
        return new PageReference('/' + recordId);           
      }      
  }

VF PAGE (DriverForm) – grandchild level
<apex:page standardcontroller="Fact_Finder__c" extensions="EditableDriverListExtension" showHeader="false" sidebar="false" >

<apex:form style="width:800px; text-align:center; margin:auto;" enctype="multipart/form-data" > 
    <apex:pageBlock >
    <apex:pageMessages id="messages"/>     
     <apex:pageBlockButtons location="bottom" > 
           <apex:commandButton action="{!doSave}" value="Save" immediate="true" styleclass="buttonsubmit" /> 
            <apex:commandButton action="{!doCancel}" value="Cancel" immediate="true" styleClass="buttoncancel" />
                </apex:pageBlockButtons> 

     <apex:outputPanel styleClass="black" layout="block">
      <apex:pageblocksection title=" Driver Details" showheader="true" collapsible="true" columns="2">                                    
                    <apex:outputfield value="{!FF.Name}"/>            
                    <apex:outputfield value="{!FF.Opportunity_Name__r.Name}"/>                      
                    <apex:outputText value="Any Driver who drives more than 12 times any one year:" style="font-weight: bold;" />
      </apex:pageblocksection>                 
     </apex:outputPanel>      
     <apex:outputPanel styleClass="black" layout="block" style="overflow: auto; width: 100%;">   
      <apex:pageblocksection showheader="false" collapsible="true" id="childList" columns="1" >
            <apex:variable var="rowNum" value="{!ZERO}" />
            <apex:outputLabel value="No Drivers currently register. Click below to Add one." rendered="{!NOT(hasChildren)}"/>
         <apex:pageBlockTable value="{!children}" var="driv" rendered="{!hasChildren}" columnsWidth="5%,10%,5%,5%,5%,5%,5%,5%,5%,5%,5%,5%,10%,5%,5%,5%,10%" >
            <apex:column headerValue=" ">
             <apex:variable var="rowNum" value="{!rowNum + 1}" />
             <apex:commandLink value="Delete" action="{!removeFromList}" rerender="childList, messages" immediate="true">
             <apex:param name="removeIndex" assignTo="{!removeIndex}" value="{!rowNum}" />
             </apex:commandLink>
            </apex:column>
            <apex:column headerValue="Driver Name" >
             <apex:inputField value="{!driv.Driver_Name__c}" style="width: 120px; height: 20px"/>
            </apex:column>
            <apex:column headerValue="DOB" >
             <apex:inputField value="{!driv.Date_of_Birth__c}" style="width: 80px; height: 20px"/>
            </apex:column>
            <apex:column headerValue="Gender" >
             <apex:inputField value="{!driv.Gender__c}" style="width: 80px; height: 20px"/>
            </apex:column>
            <apex:column headerValue="License Class" >
             <apex:inputField value="{!driv.Class_of_License__c}" style="width: 80px; height: 20px" />   
            </apex:column>
            <apex:column headerValue="License No." >
             <apex:inputField value="{!driv.Licence_Number__c}" style="width: 80px; height: 20px" />   
            </apex:column>
…….
         </apex:pageBlockTable> 
             <apex:commandButton value="Add Driver" action="{!addToList}" rerender="childList, messages" immediate="true" styleclass="buttonadd" />
      </apex:pageblocksection>
     </apex:outputPanel>    
    </apex:pageBlock>
  </apex:form>
</apex:page>
Extension (EditableDriverListExtension)
public with sharing class EditableDriverListExtension extends EditableList
{
   public Fact_Finder__c FF {get; private set;}
   string FFId = ApexPages.currentPage().getParameters().get('FFId');   
   
  public EditableDriverListExtension(ApexPages.StandardController stdController) 
  {
    super(stdController);
     
    this.FF = [SELECT Id, Name, Opportunity_Name__r.Name FROM Fact_Finder__c WHERE Id =:ApexPages.currentPage().getParameters().get('FFId')];              
    
    this.childList = [SELECT Id,
                          Motor_Fact_Finder_No__c,
                          Driver_Name__c,
                          Date_of_Birth__c,
                          Gender__c,
                          Class_of_License__c,
                          Licence_Number__c
…..
                      FROM FFDriver__c
                      WHERE Motor_Fact_Finder_No__c =: mysObject.Id];                                          
    }
  public List<FFDriver__c> getChildren()  {
    return (List<FFDriver__c>)childList;
  }
  public override sObject initChildRecord()  {
    FFDriver__c child = new FFDriver__c();
       
    child.Motor_Fact_Finder_No__c = FF.Id;
    child.Opportunity_Name__c = FF.Opportunity_Name__r.Name; 
    child.Accidents__c= 'No'; 
    child.Claims_last_5_years__c= 'No';
    child.Convictions__c= 'No';
    child.Licence_Suspended_or_Cancelled__c= 'No';
    child.Claims_Bonus__c= 'No';  
    child.Restricted_Nominated_Driver_Policy__c= 'No';  
    child.Is_the_driver_less_than_25__c= 'No';              
    return child;
  }
    public PageReference doCancel(){      
         return new PageReference('/' +FF.Opportunity_Name__r.Id);    
      }      
        public PageReference doSave(){       
        try{  
             upsert childList;  
                pageReference pageRef = new PageReference('/'+FF.Opportunity_Name__r.Id);  
                pageRef.setRedirect(true);  
                return pageRef;      
        }catch(DMLException saveEx){                 
                return null;  
         }      
         return null;  
    }  
  }
Extend (EditableList)
public abstract with sharing class EditableList 
{
  public final Integer ZERO {get; private set;}

  public sObject mysObject {get; protected set;}
  public List<sObject> childList {get; set;}  

  public String removeIndex {get; set;}
  @TestVisible protected List<sObject> removeChildList {get;set;} 

  public EditableList()
  {
    this.ZERO = 0;
    this.removeChildList = new List<sObject>();
    this.childList = new List<sObject>();
  }

    public EditableList(ApexPages.StandardController stdController)   {
    this();
    this.mysObject = (sObject)stdController.getRecord();
  } 
  public Boolean getHasChildren()  {
    return !childList.isEmpty();
  }
  public virtual sObject initChildRecord()  {   
    return new FFDriver__c();
  }
  public void addToList()  {
    childList.add(initChildRecord());
  }
  public void removeFromList()  {
    try
    {
      Integer rowIndex = Integer.valueOf(removeIndex) - 1;      
      if (childList.size() > rowIndex && rowIndex >= 0)      {
        sObject sobj = childList.remove(rowIndex);      
             if (sobj.Id != null)        {       
          removeChildList.add(sobj);
        }
      }
    }
    catch (Exception e)    {
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
    }
  }
public PageReference save()     {  
     Savepoint sp = Database.setSavepoint();                 
     try   {  
       List<sObject> insertChildList = new List<sObject>();  
       List<sObject> updateChildList = new List<sObject>();  
       for (sObject sobj : childList)   {  
         if (sobj.Id == null)  {  
           insertChildList.add(sobj);  
         }  
         else  {  
           updateChildList.add(sobj);  
         }  
       }   
       insert insertChildList;  
       update updateChildList;  
       delete removeChildList;           
       return new PageReference('/' + mysObject.Id);   
     }  
     catch(Exception e)   {  
       Database.rollback(sp);                     
       ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));                 
       return null;  
     }   
   }   
 }

Thank you in advance for your help.
Sylvie
SFDC9999SFDC9999
@SYlvie,

I just relaised that even i have the same issue . Unless i eneter all the values for all the fieldsa in the Mutiple lines it does not save .
Rogerio Lara 2028Rogerio Lara 2028
Hi there, I have a very similar challenge and I was wondering if you could enlight my way so can do the below:

I've been trying to do this for the past week, but I'm not getting anywhere...

I have 2 custom objects and I am trying to get the child to be created on insert of parent.

I'm trying to creat an edit visualforce page, so that when I create a new Opportunity Positioning, I will, on the same page layout,be able to also create and save Buying Influence 1,2,3 etc. I know that I will have to override the 'new' button. for the Opportunity Positioning for the new visualforce page.

Any ideas of the best way to do this?

<apex:page standardcontroller="Opportunity_Positioning__c">
<apex:messages />
    <apex:sectionheader title="{!$ObjectType.Opportunity_Positioning__c.label} Edit" subtitle="{!IF(ISNULL(Opportunity_Positioning__c.Name), 'New Strategic Client Opportunity Plan',Opportunity_Positioning__c.Name)}"/>
    <apex:form >
        <apex:pageblock mode="edit" title="{!$ObjectType.Opportunity_Positioning__c.label} Edit">
            <apex:pageblockbuttons >
                <apex:commandbutton value="Save" action="{!Save}"/>
                <apex:commandbutton value="Cancel" action="{!Cancel}"/>
            </apex:pageblockbuttons>

            <!-- **********   [Record Type : Master ]   **********  -->
            <apex:outputpanel >
                <apex:pageblocksection title="Information" showheader="true" columns="2">
                    <apex:inputfield value="{!Opportunity_Positioning__c.Name}" required="true"/>
                    <apex:pageblocksectionitem />
                    <apex:inputfield value="{!Opportunity_Positioning__c.Opportunity__c}" required="true"/>
                    <apex:pageblocksectionitem />
                </apex:pageblocksection>
                <apex:pageblocksection title="Summary of my position today" showheader="true" columns="2">
                    <apex:inputfield value="{!Opportunity_Positioning__c.Current_Status__c}" required="false"/>
                    <apex:inputfield value="{!Opportunity_Positioning__c.Key_Actions_Required__c}" required="false"/>
                    <apex:inputfield value="{!Opportunity_Positioning__c.Strengths__c}" required="false"/>
                    <apex:inputfield value="{!Opportunity_Positioning__c.Red_Flags__c}" required="false"/>
                    <apex:pageblocksectionitem />
                    <apex:inputfield value="{!Opportunity_Positioning__c.Adequacy_of_Current_Position__c}" required="false"/>
                </apex:pageblocksection>
                <apex:pageblocksection title="Competitive Positioning" showheader="true" columns="2">
                    <apex:inputfield value="{!Opportunity_Positioning__c.Position_vs_c__c}" required="false"/>
                    <apex:inputfield value="{!Opportunity_Positioning__c.Primary_Competitor__c}" required="false"/>
                </apex:pageblocksection>
            </apex:outputpanel>
        </apex:pageblock>
    </apex:form>
    </apex:page>

and

apex:page standardcontroller="Buying_Influence__c">
<apex:messages />
    <apex:sectionheader title="{!$ObjectType.Buying_Influence__c.label} Edit" subtitle="{!IF(ISNULL(Buying_Influence__c.Name), 'New Buying Influence',Buying_Influence__c.Name)}"/>
    <apex:form >
        <apex:pageblock mode="edit" title="{!$ObjectType.Buying_Influence__c.label} Edit">
            <apex:pageblockbuttons >
                <apex:commandbutton value="Save" action="{!Save}"/>
                <apex:commandbutton value="Cancel" action="{!Cancel}"/>
            </apex:pageblockbuttons>

            <!-- **********   [Record Type : Master ]   **********  -->
            <apex:outputpanel >
                <apex:pageblocksection title="Information" showheader="true" columns="2">
                    <apex:inputfield value="{!Buying_Influence__c.Name}" required="true"/>
                    <apex:inputfield value="{!Buying_Influence__c.SCOP__c}" required="true"/>
                    <apex:inputfield value="{!Buying_Influence__c.Name__c}" required="false"/>
                    <apex:pageblocksectionitem />
                    <apex:inputfield value="{!Buying_Influence__c.Buying_influence_role__c}" required="false"/>
                    <apex:pageblocksectionitem />
                    <apex:inputfield value="{!Buying_Influence__c.Degree_of_Influence__c}" required="true"/>
                    <apex:pageblocksectionitem />
                    <apex:inputfield value="{!Buying_Influence__c.Mode__c}" required="true"/>
                    <apex:pageblocksectionitem />
                </apex:pageblocksection>
                <apex:pageblocksection title="How well is based covered for this contact" showheader="true" columns="1">
                    <apex:inputfield value="{!Buying_Influence__c.Rating_for_base_covered__c}" required="true"/>
                    <apex:inputfield value="{!Buying_Influence__c.Evidence_to_support_your_rating__c}" required="false"/>
                </apex:pageblocksection>
            </apex:outputpanel>
        </apex:pageblock>
    </apex:form>
Sylvie SerpletSylvie Serplet
My problem was caused by the attribute immediate=true in the VF page in the save button. By removing it, the getters/setters are fire correctly and the input values are captured and saved as requested.
<apex:commandButton action="{!doSave}" value="Save" styleclass="buttonsubmit" />