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
d.tejdeep@nicomatic.ind.tejdeep@nicomatic.in 

dynamic insert parent and child in salesforce


I want to insert Multiple parent and child (Account and contacts) in Salesforce lightning. One parent and child set, multiple children if required.User-added image
Parent component :
 
<!--Parent-->
<aura:component controller="AuraSampleController" Implements="flexipage:availableForRecordHome,force:hasRecordId">
    <!--Init handler which is call doInit js function on component Load--> 
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <!--Event handler for Add and Delete Row Event which is execute from Child Component-->   
    <aura:handler name="DeleteRowEvent" event="c:DeleteRowEvent" action="{!c.removeDeletedRow}"/>
    <aura:handler name="AddRowEvent" event="c:AddRowEvent" action="{!c.addRow}"/>

    <!--Aura Attribute for store Account Object List as Array-->   
    <aura:attribute name="AccountList" type="Account[]"/> 

    <!--Header Part-->       
    <div class="slds-page-header">
        <h1 class="slds-page-header__title">Create Multiple Accounts and contacts in Lightning</h1>
    </div>

    <!--Table Part-->          
    <table class="slds-table slds-table_bordered slds-table_cell-buffer"> 
        <thead>
            <tr class="slds-text-title_caps">
                <th scope="col">
                    <div class="slds-truncate">#</div>
                </th>
                <th scope="col">
                    <div class="slds-truncate" title="Account Name">Account Name</div>
                </th>
                <th scope="col">
                    <div class="slds-truncate" title="Account Number">Account Number</div>
                </th>
                <th scope="col">
                    <div class="slds-truncate" title="Phone">Phone</div>
                </th>
                 <th scope="col">
                    <div class="slds-truncate" title="Action">Action</div>
                </th>
            </tr>           
        </thead>   
        <tbody>
            <!--Iterate the child Component for display Table rows 
               with pass the List Item Index for track the Every child Component 
               and pass each List Account Instance -->        
            <aura:iteration items="{!v.AccountList}" var="item" indexVar="index">
                <c:Child AccountInstance="{!item}" rowIndex="{!index}" />
            </aura:iteration>
        </tbody>
    </table>
    <br/>
    <!--Save Button which is call Save js function on click -->
    <button class="slds-button slds-button_brand"  onclick="{!c.Save}">Save</button>
</aura:component>

parent controller :
({  
    // function call on component Load
    doInit: function(component, event, helper) {
        // create a Default RowItem [Account Instance] on first time Component Load
        // by call this helper function  
        helper.createObjectData(component, event);
    },

    // function for save the Records 
    Save: function(component, event, helper) {
        // first call the helper function in if block which will return true or false.
        // this helper function check the "Account Name" will not be blank on each row.
        if (helper.validate(component, event)) {
            // call the apex class method for save the Account List
            // with pass the contact List attribute to method param.  
            var action = component.get("c.SaveAccounts");
            action.setParams({
                "accList": component.get("v.AccountList")
            });
            // set call back 
            action.setCallback(this, function(response) {
                var state = response.getState();
                if (state === "SUCCESS") {
                    // if response if success then reset the 'AccountList' Attribute 
                    // and call the common helper method for create a default Object Data to Account List 
                    component.set("v.AccountList", []);
                    helper.createObjectData(component, event);
                    alert('Account records saved successfully');
                }
            });
            // enqueue the server side action  
            $A.enqueueAction(action);
        }
    },

    // function for create new object Row in Contact List 
    addRow: function(component, event, helper) {
        // call the comman "createObjectData" helper method for add new Object Row to List  
        helper.createObjectData(component, event);
    },

    // function for delete the row 
    removeDeletedRow: function(component, event, helper) {
        //get the selected row Index for delete, from Lightning Event Attribute  
        var index = event.getParam("indexVar");
        //get the all List (AccountList attribute) and remove the Object Element Using splice method    
        var AllRowsList = component.get("v.AccountList");
        AllRowsList.splice(index, 1);
        //set the AccountList after remove selected row element  
        component.set("v.AccountList", AllRowsList);
    },
})

Parent Helper :
 
({
    createObjectData: function(component, event) {
        //get the AccountList from component and add(push) New Object to List  
        var RowItemList1 = component.get("v.AccountList");
        RowItemList1.push({
            'sobjectType': 'Account',
            'Name': '',
            'AccountNumber': '',
            'Phone': ''
        });
        // set the updated list to attribute (AccountList) again    
        component.set("v.AccountList", RowItemList1);
    },
    //helper function for check if Account Name is not null/blank on save  
    validate: function(component, event) {
        var isValid = true;
        var allAccountRows = component.get("v.AccountList");
        for (var indexVar = 0; indexVar < allAccountRows.length; indexVar++) {
            if (allAccountRows[indexVar].Name == '') {
                isValid = false;
                alert('Account Name Cannot be blank on row number ' + (indexVar + 1));
            }
        }
        return isValid;
    },
})

Child Component :
 
<!-- Register 2 Lightning Event for handle add or Delete rows on Parent Component  -->
<aura:registerEvent name="DeleteRowEvent" type="c:DeleteRowEvent"/> 
<aura:registerEvent name="AddRowEvent" type="c:AddRowEvent"/> 

<!-- Table Row -->  
<tr class="slds-text-title_caps">
    <td> 
        {!v.rowIndex + 1}
    </td>
    <td>
        <ui:inputText class="slds-input" value="{!v.AccountInstance.Name}"/>
    </td>
    <td>
        <ui:inputText class="slds-input" value="{!v.AccountInstance.AccountNumber}"/>
    </td>
    <td>
        <ui:inputPhone class="slds-input" value="{!v.AccountInstance.Phone}"/>
    </td>
    <td>
        <!-- conditionally Display Add or Delete Icons, if rowIndex is 0 then show add row Icon else show delete Icon-->
        <aura:if isTrue="{!v.rowIndex == 0}">
            <a onclick="{!c.addRow}">
                <lightning:icon iconName="utility:add" class="slds-icon slds-icon_small" size="small" alternativeText="Add"/>
                <span class="slds-assistive-text">Add</span>
            </a>    
            <aura:set attribute="else">
                <a onclick="{!c.deleteRow}">
                    <lightning:icon variant="error" iconName="utility:delete" class="slds-icon slds-icon_small" size="small" alternativeText="Delete"/>
                    <span class="slds-assistive-text">Delete</span>
                </a>
            </aura:set> 
        </aura:if>
    </td>
</tr>
    <br/>




    <table class="slds-table slds-table_bordered slds-table_cell-buffer"> 
    <thead>
        <tr class="slds-text-title_caps">
             <th scope="col">
                <div class="slds-truncate" title="No">S.NO</div>
            </th>
             <th scope="col">
                <div class="slds-truncate" title="First Name">Contact Name</div>
            </th>
               <th scope="col">
                <div class="slds-truncate" title="Action">Action</div>
            </th>
            </tr>         
    </thead>   
    <tbody>
        <!--Iterate the child Component for display Table rows 
           with pass the List Item Index for track the Every child Component 
           and pass each List Account Instance -->        
        <aura:iteration items="{!v.ContactList}" var="item" indexVar="index">
            <c:Contact ContactInstance="{!item}"  rowIndex="{!index}"/>
        </aura:iteration>    
    </tbody>
</table>

child js :
 
({
        // function call on component Load
    doInit: function(component, event, helper) {
        // create a Default RowItem [contact Instance] on first time Component Load
        // by call this helper function  
        helper.createObjectData1(component, event);
    },

    addRow : function(component, event, helper){
        //Execute the AddRowEvent Lightning Event 
        component.getEvent("AddRowEvent").fire();     
    },

    deleteRow : function(component, event, helper){
        //Execute the DeleteRowEvent Lightning Event and pass the deleted Row Index to Event attribute
        component.getEvent("DeleteRowEvent").setParams({"indexVar" : component.get("v.rowIndex") }).fire();
    },

      // function for create new object Row in Contact List 
    addingRow: function(component, event, helper) {
        // call the comman "createObjectData" helper method for add new Object Row to List  
        helper.createObjectData1(component, event);
    },

    // function for delete the row 
    removeDeletedRow: function(component, event, helper) {
        //get the selected row Index for delete, from Lightning Event Attribute  
        var index = event.getParam("indexVar");
        //get the all List (ContactList attribute) and remove the Object Element Using splice method    
        var AllRowsList = component.get("v.ContactList");
        AllRowsList.splice(index, 1);
        //set the ContactList after remove selected row element  
        component.set("v.ContactList", AllRowsList);
    }
})

child helper :
 
({
    createObjectData1: function(component, event) {
        //get the ContactList from component and add(push) New Object to List  
        var RowItemList = component.get("v.ContactList");
        RowItemList.push({
            'sobjectType': 'Contact',
            'FirstName': ''
        });
        // set the updated list to attribute (ContactList) again    
        component.set("v.ContactList", RowItemList);
    },
    //helper function for check if Contact Name is not null/blank on save  
    validate: function(component, event) {
        var isValid = true;
        var allContactRows = component.get("v.ContactList");
        for (var indexVar = 0; indexVar < allContactRows.length; indexVar++) {
            if (allContactRows[indexVar].FirstName == '') {
                isValid = false;
                alert('Contact Name Cannot be blank on row number ' + (indexVar + 1));
            }
        }
        return isValid;
    },
})

Contact Component :
 
<!--Child-->
<aura:component >    
    <!--Attribute for store single Contact object instance-->
    <aura:attribute name="ContactInstance" type="Contact"/>
    <!--Attribute for store Index of Particular Instance -->
    <aura:attribute name="rowIndex" type="String"/>

    <!-- Register 2 Lightning Event for handle add or Delete rows on Parent Component  -->
    <aura:registerEvent name="DeleteRowEvent" type="c:DeleteRowEvent"/> 
    <aura:registerEvent name="AddRowEvent" type="c:AddRowEvent"/> 

    <!-- Table Row -->  
    <tr class="slds-text-title_caps">
        <td> 
            {!v.rowIndex + 1}
        </td>
        <td>
            <ui:inputText class="slds-input" value="{!v.ContactInstance.FirstName}"/>
        </td>
        <td>
            <!-- conditionally Display Add or Delete Icons, if rowIndex is 0 then show add row Icon else show delete Icon-->
            <aura:if isTrue="{!v.rowIndex == 0}">
                <a onclick="{!c.addRow}">
                    <lightning:icon iconName="utility:add" class="slds-icon slds-icon_small" size="small" alternativeText="Add"/>
                    <span class="slds-assistive-text">Add</span>
                </a>    
                <aura:set attribute="else">
                    <a onclick="{!c.deleteRow}">
                        <lightning:icon variant="error" iconName="utility:delete" class="slds-icon slds-icon_small" size="small" alternativeText="Delete"/>
                        <span class="slds-assistive-text">Delete</span>
                    </a>
                </aura:set> 
            </aura:if>
        </td> 
    </tr>

</aura:component>

Contact Controller :
 
({
addRow : function(component, event, helper){
        //Execute the AddRowEvent Lightning Event 
        component.getEvent("AddRowEvent").fire();     
    },

    deleteRow : function(component, event, helper){
        //Execute the DeleteRowEvent Lightning Event and pass the deleted Row Index to Event attribute
        component.getEvent("DeleteRowEvent").setParams({"indexVar" : component.get("v.rowIndex") }).fire();
    }

 })

When I click on iteration add button.The iteration is happening for parent and child.By using this code you can see two add button in both parent and child . when i clik on child add.It is adding parent as well.I want to add child when i click on child button.I want to parent and child set when i click on parent button.
 
Kuldeep Singh 102Kuldeep Singh 102
Hi Tejdeep,

Could you provide the details of events, so that i can simulate the code in my org.

Regards,
Kuldeep Singh
d.tejdeep@nicomatic.ind.tejdeep@nicomatic.in
AddRowEvent
 
<aura:event type="COMPONENT" description="Event to add row"></aura:event>

DeleteRowEvent
 
<aura:event type="COMPONENT" description="Event to delete row" >
    <aura:attribute name="indexVar" type="Integer" description="Use For Delete Row" />
</aura:event>



 
Touqeer khanTouqeer khan
Hi Tejdeep,

Can you please share the working code with me.

Thanks
Vishesh kant Aggarwal 17Vishesh kant Aggarwal 17

Hi Tejdeep,

please share the working code with class and everything?