I am using a package from Michael Welburn GitHub to create multiple records for my Custom Object (FFDriver__c). One precision, I am working in Lightning.

My configuration:

3 Objects - All with Master-Detail relationship.:

  • Opportunity (parent)
  • Fact_Finder__c (child)
  • FFDriver__c (grandchild).

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. VF Page DriverForm

I have tried to simplify the code (taking out styles and many fields). Sorry it is still very long and the formatting terrible….

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: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: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:column headerValue="Driver Name" >
                                <apex:inputField value="{!driv.Driver_Name__c}" style="width: 120px; height: 20px"/>
                            <apex:column headerValue="DOB" >
                                <apex:inputField value="{!driv.Date_of_Birth__c}" style="width: 80px; height: 20px"/>
                            <apex:column headerValue="Gender" >
                                <apex:inputField value="{!driv.Gender__c}" style="width: 80px; height: 20px"/>
                        <apex:commandButton value="Add Driver" action="{!addToList}" rerender="childList, messages" immediate="true" styleclass="buttonadd" />

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){
            this.FF = [SELECT Id, Name, Opportunity_Name__r.Name FROM Fact_Finder__c WHERE Id =:ApexPages.currentPage().getParameters().get('FFId')];
            this.childList = [SELECT Id,
            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(){
                upsert childList;
                pageReference pageRef = new PageReference ('/'+FF.Opportunity_Name__r.Id);
                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.mysObject = (sObject) stdController.getRecord();
    public Boolean getHasChildren() {
        return !childList.isEmpty();
    public virtual sObject initChildRecord() {
        return new FFDriver__c();
    public void addToList() {
    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) {
        } 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) {
                else {
            insert insertChildList;
            update updateChildList;
            delete removeChildList;
            return new PageReference('/' + mysObject.Id);
        } catch (Exception e) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
            return null;


debug log:

'16:09:16:041 USER_DEBUG [51]|DEBUG|(FFDriver__c:{Motor_Fact_Finder_No__c=a0OO0000007hDOhMAM, Opportunity_Name__c=test motor - driver, Accidents__c=No, Claims_last_5_years__c=No, Convictions__c=No, Licence_Suspended_or_Cancelled__c=No, Claims_Bonus__c=No, Restricted_Nominated_Driver_Policy__c=No, Is_the_driver_less_than_25__c=No}, FFDriver__c:{Motor_Fact_Finder_No__c=a0OO0000007hDOhMAM, Opportunity_Name__c=test motor - driver, Accidents__c=No, Claims_last_5_years__c=No, Convictions__c=No, Licence_Suspended_or_Cancelled__c=No, Claims_Bonus__c=No, Restricted_Nominated_Driver_Policy__c=No, Is_the_driver_less_than_25__c=No})'

Thank you in advance for your help. Sylvie.

  • Sylvie, I tried the similar code in my org and works in both classic and lightning environment. So the issue should be somewhere else. My suggestions are: 1. add a System.debug for ChildList value before do upsert in doSave() function. See whether the values are correct and whether you can manually upsert those values 2. Add a apex:pageMessages section to find out the error messages. – Lance Shi Sep 5 '16 at 23:42
  • Hi @LanceShi, sorry for the late reply, I was away last week. All the values that are hardcoded in the initChildRecord are upserted correctly but none that I entered manually. It is also what the debug log tells me. – ultima67 Sep 12 '16 at 2:22
  • So you are saying that before the line: upsert childList in your controller, you debugged childList and it was not the correct value? I tried with similar code in my org but didn't repro for me. I wouldn't say it is lightning issue. And plus, I really don't see a reason you need to use a framework here. – Lance Shi Sep 12 '16 at 2:59
  • It upsert only the value that are hardcoded in the initChildRecord but not the other ones such as driver name, DOB, gender that I entered manually in my form (see image above). What do you recommend? Thank you. – ultima67 Sep 12 '16 at 4:16
  • Are you sure you have added a System.debug(childList) line before the line: upsert childList? What is the output? Before you click the save button, click Add Driver button for several times and then click save. What will happen in the debug log? – Lance Shi Sep 12 '16 at 5:05

The 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" />

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.