In below example I’m adding account record in Salesforce Lightning Component with Add Delete Rows functionality.
Apex Class:
public with sharing class AuraSampleController{ @AuraEnabled public static void saveAccounts(List<Account> accList){ Insert accList; } }
Lightning Component:
<aura:component controller="AuraSampleController" Implements="flexipage:availableForRecordHome,force:hasRecordId"> <aura:attribute name="accountList" type="Account[]"/> <div class="slds-m-around--xx-large"> <div class="slds-float_right slds-p-bottom_small"> <h1 class="slds-page-header__title">Add Row <lightning:buttonIcon iconName="utility:add" size="large" variant="bare" alternativeText="Add" onclick="{!c.addRow}"/> </h1> </div> <div class="container-fluid"> <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> <aura:iteration items="{!v.accountList}" var="acc" indexVar="index"> <tr> <td> {!index + 1} </td> <td> <lightning:input name="accName" type="text" required="true" maxlength="50" label="Account Name" value="{!acc.Name}" /> </td> <td> <lightning:input name="accNumber" type="text" maxlength="10" label="Account Number" value="{!acc.AccountNumber}" /> </td> <td> <lightning:input name="accPhone" type="phone" maxlength="10" label="Phone" value="{!acc.Phone}" /> </td> <td> <a onclick="{!c.removeRow}" data-record="{!index}"> <lightning:icon iconName="utility:delete" size="small" alternativeText="Delete"/> <span class="slds-assistive-text">Delete</span> </a> </td> </tr> </aura:iteration> </tbody> </table> <div class="slds-align_absolute-center slds-p-top_small"> <lightning:button variant="brand" label="Submit" title="Brand action" onclick="{!c.save}" /> </div> </div> </div> </aura:component>
Lightning JS Controller:
({ addRow: function(component, event, helper) { helper.addAccountRecord(component, event); }, removeRow: function(component, event, helper) { //Get the account list var accountList = component.get("v.accountList"); //Get the target object var selectedItem = event.currentTarget; //Get the selected item index var index = selectedItem.dataset.record; accountList.splice(index, 1); component.set("v.accountList", accountList); }, save: function(component, event, helper) { if (helper.validateAccountList(component, event)) { helper.saveAccountList(component, event); } }, })
Lightning JS Helper:
({ addAccountRecord: function(component, event) { //get the account List from component var accountList = component.get("v.accountList"); //Add New Account Record accountList.push({ 'sobjectType': 'Account', 'Name': '', 'AccountNumber': '', 'Phone': '' }); component.set("v.accountList", accountList); }, validateAccountList: function(component, event) { //Validate all account records var isValid = true; var accountList = component.get("v.accountList"); for (var i = 0; i < accountList.length; i++) { if (accountList[i].Name == '') { isValid = false; alert('Account Name cannot be blank on row number ' + (i + 1)); } } return isValid; }, saveAccountList: function(component, event, helper) { //Call Apex class and pass account list parameters var action = component.get("c.saveAccounts"); action.setParams({ "accList": component.get("v.accountList") }); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { component.set("v.accountList", []); alert('Account records saved successfully'); } }); $A.enqueueAction(action); }, })