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
    Commented Sep 5, 2016 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
    Commented Sep 12, 2016 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
    Commented Sep 12, 2016 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
    Commented Sep 12, 2016 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
    Commented Sep 12, 2016 at 5:05

1 Answer 1


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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .