Add Delete Row Dynamic In Lightning Component : Sample Code
Hi Guys,
Today in this post we are going to learn, How to Add Delete Rows Dynamic In Salesforce Lightning Component By Using Client Side JavaScript Controller.
In this post, we are created 2 sample lightning component, by these lightning components You can create multiple records as your requirement by Adding or Deleting new rows on UI. we will also make, ‘first name’ as a required Input field
Component Blue Print :
For done this we have created 2 Lightning Components and 2 Lightning Events for pass values/actions from child component to parent. Events can contain attributes that can be set before the event is fired and read when the event is handled.
Step 1 : Create Lightning Event : AddNewRowEvt.evt
From Developer Console >> File >> New >> Lightning Event
<aura:event type="COMPONENT" description="Use For Add New Row"></aura:event>
Step 2 : Create Lightning Event : DeleteRowEvt.evt
From Developer Console >> File >> New >> Lightning Event
<aura:event type="COMPONENT" description="Event to remove Row" > <aura:attribute name="indexVar" type="Integer" description="Use For Delete Row" /> </aura:event>
Step 3 : Create Lightning Component : dynamicRowItem.cmp [Child Component]
From Developer Console >> File >> New >> Lightning Component
<!-- sfdcMonkey.com --> <!-- Child Lightning Component for Create New Row Instance--> <aura:component > <!-- Aura Attribute for store single Contact[standard Object] Instance And Store Index of Particular Instance --> <aura:attribute name="ContactInstance" type="Contact"/> <aura:attribute name="rowIndex" type="String"/> <!-- Register 2 Lightning Event for handle add or Delete rows on Parent Component --> <aura:registerEvent name="DeleteRowEvt" type="c:DeleteRowEvt"/> <aura:registerEvent name="AddRowEvt" type="c:AddNewRowEvt"/> <!-- 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> <ui:inputText class="slds-input" value="{!v.ContactInstance.LastName}"/> </td> <td> <ui:inputPhone class="slds-input" value="{!v.ContactInstance.Phone}"/> </td> <td> <!-- conditionally Display Add or Delete Icons if rowIndex is 0 then show Add New Row Icon else show delete Icon --> <aura:if isTrue="{!v.rowIndex == 0}"> <a onclick="{!c.AddNewRow}"> <lightning:icon iconName="utility:add" class="slds-icon slds-icon_small" size="small" alternativeText="add"/> <span class="slds-assistive-text">Add Icon</span> </a> <aura:set attribute="else"> <a onclick="{!c.removeRow}"> <lightning:icon variant="error" iconName="utility:delete" class="slds-icon slds-icon_small" size="small" alternativeText="icon"/> <span class="slds-assistive-text">Delete Icon</span> </a> </aura:set> </aura:if> </td> </tr> </aura:component>
- See Code Comments.
JavaScript Controller : dynamicRowItemController.js
({ AddNewRow : function(component, event, helper){ // fire the AddNewRowEvt Lightning Event component.getEvent("AddRowEvt").fire(); }, removeRow : function(component, event, helper){ // fire the DeleteRowEvt Lightning Event and pass the deleted Row Index to Event parameter/attribute component.getEvent("DeleteRowEvt").setParams({"indexVar" : component.get("v.rowIndex") }).fire(); }, })
- See Code Comments.
Step 4 : Create Apex Controller : addDeleteController.apxc
From Developer Console >> File >> New >> Apex Class
public with sharing class addDeleteController { @AuraEnabled public static void saveContacts(List<Contact> ListContact){ Insert ListContact; } }
- By above apex controller we are save the contacts.
Step 5 : Create Lightning Component : dynamicRow.cmp [Parent Component]
From Developer Console >> File >> New >> Lightning Component
<!--sfdcmonkey.com--> <!--Parent Lightning Compomemt--> <aura:component controller="addDeleteController" 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 fire from Child Component--> <aura:handler name="DeleteRowEvt" event="c:DeleteRowEvt" action="{!c.removeDeletedRow}"/> <aura:handler name="AddRowEvt" event="c:AddNewRowEvt" action="{!c.addNewRow}"/> <!--Aura Attribute for store Contact Object List as Array--> <aura:attribute name="contactList" type="Contact[]"/> <!--Header Part--> <div class="slds-page-header"> <h1 class="slds-page-header__title">Create Multiple Contacts, With Add/Delete Rows Dynamically</h1> <p class="slds-text-body_small slds-line-height_reset">By sfdcmonkey.com</p> </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">S.No</div> </th> <th scope="col"> <div class="slds-truncate" title="First Name">First Name</div> </th> <th scope="col"> <div class="slds-truncate" title="Last Name">Last Name</div> </th> <th scope="col"> <div class="slds-truncate" title="Phone">Phone</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 Contact Instance --> <aura:iteration items="{!v.contactList}" var="item" indexVar="index"> <c:dynamicRowItem ContactInstance="{!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>
- See Code Comments.
JavaScript Controller : dynamicRowController.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.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 "first Name" will not be blank on each row. if (helper.validateRequired(component, event)) { // call the apex class method for save the Contact List // with pass the contact List attribute to method param. var action = component.get("c.saveContacts"); action.setParams({ "ListContact": component.get("v.contactList") }); // set call back action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { // if response if success then reset/blank the 'contactList' Attribute // and call the common helper method for create a default Object Data to Contact List component.set("v.contactList", []); helper.createObjectData(component, event); alert('record Save'); } }); // enqueue the server side action $A.enqueueAction(action); } }, // function for create new object Row in Contact List addNewRow: 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 (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); }, })
- See Code Comments.
JavaScript Helper : dynamicRowHelper.js
({ createObjectData: 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': '', 'LastName': '', 'Phone': '' }); // set the updated list to attribute (contactList) again component.set("v.contactList", RowItemList); }, // helper function for check if first Name is not null/blank on save validateRequired: 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('First Name Can\'t be Blank on Row Number ' + (indexVar + 1)); } } return isValid; }, })
- See Code Comments.
From developer console >> file >> new >> Lightning Application
demo.app [Lightning Application]
<aura:application extends="force:slds"> <c:dynamicRow/> <!-- here c: is org. default namespace prefix--> </aura:application>
Output:
Related Resource:
Like our facebook page for new post updates. & Don’t forget to bookmark this site for your future reference.
if you have any suggestions or issue with it, you can post in comment box 🙂
47 comments
This page has an error. You might just need to refresh it. Action failed: c:dynamicRow$controller$Save [i is not defined] Failing descriptor: {c:dynamicRow$controller$Save} i m getting error can u help me out?
Hi jagannath,
sorry my Typo mistake in the javaScript helper code of dynamicRowHelper [Line number 18].
Please correct for loop last parameter, Use indexVar++ InsteadOf i++
for (var indexVar = 0; indexVar < allContactRows.length; indexVar++) {
Thanks for inform on this
Its F9 nd Thank Q so much
This page has an error. You might just need to refresh it. i m getting the following errors can u help me out?
Error in $A.getCallback() [Cannot read property ‘FirstName’ of null]
Error in $A.getCallback() [Cannot read property ‘LastName’ of null]
Error in $A.getCallback() [Cannot read property Phone’ of null]
When click on Add button
This page has an error. You might just need to refresh it.
Action failed: c:dynamicRowItem$controller$AddNewRow [Cannot read property ‘fire’ of null]
Failing descriptor: {c:dynamicRowItem$controller$AddNewRow}
are you using the same above code ?
Is it possible to have picklist as one of the column per row?
I am not able to assign the text box value to the contact record, can you please let me know the reason for that.
are you using the same code ? Lightning Component and JavaScript are case sensitive, make sure your Object API field Names are correct
My record created is not taking the value from the textbox
Hay
This Page has an error .You might just need to refresh it.Like.
Error in $A.getCallback() [Cannot read property ‘FirstName’ of null]
How can I use look up and currency field.
Hello,
Thanks for providing this sample code. It is really helpful in Salesforce Lightning Development
Hi,
It’s just a wonderful article and I am following daily for my knowledge.
Keep updating the things which are related to lightning
Thanks nice collection
Hello,
I’m very new to SFD and love, love, love your posts here. I am using your above example (modifying a little to make it my own) and made two components, the one component works like a dream but the other throws an error when I try to delete a row. The only difference is the one has an ui:inputSelect field and thats the field that’s causing the error. It actually does delete the row but I always get this error. Again I don’t have this problem on my other component that is identical to this other than it does not have an inputSelect control. Any thoughts?
Error:
Uncaught Action failed: ui:inputSelect$controller$valueChange [Cannot read property ‘inputselect field’ of undefined]
Callback failed: apex://FormController/ACTION$deleteLineItem
Thanks again for sharing your knowledge and helping us learn.
Thanks for the code. Can you just help me with below requirement :
I want to show this dynamic row adding with 3 fields inside another parent component and save the 3 fields value on that parent object. How to achieve this functionality? Need help, to get a way to do it.
Hi,
I’m getting below error . Please help. I’m using this on custom object and field is picklist which is throwing error.
This page has an error. You might just need to refresh it. Action failed: ui:inputSelect$controller$valueChange [Cannot read property ‘Company__c’ of undefined] Callback failed: apex://addDeleteController/ACTION$saveCars Failing descriptor: {ui:inputSelect$controller$valueChange}
Hi,
I am getting error :”Cannot read property ‘FirstName’ of null”
Ive used this way of iterating over a component to add multiple rows but only one rows gets added during initialization. Consequent actions to add rows prove futile.
I want to limit the addition of new row to 10 rows, how do i do it?
HI kuldeep, kindly post your query/issue/requirement here :
https://developer.salesforce.com/forums#!/feedtype=RECENT&criteria=ALLQUESTIONS&
LastName is the required field, not the FirstName.
yep, i know. it’s just an example to show how we can make fields required dynamically
This page has an error. You might just need to refresh it. Unknown controller action ‘AddNewRow’ Failing descriptor: {markup://c:dynamicRowItem}
Can you please share the test code for above Apex class.
post your issue on developer forums in more details and share question URL here, so i can look into your issue. Thanks
https://developer.salesforce.com/forums
This worked out great! Where can I find information on adding a picklist to the table and using with the controllers?
Fantastic, what a time saver. Many thanks for this.
How do we insert these multiple contacts with Account?
Basically, how do we insert records with lookup field(using recordEditForm)
Is there any way to put delete functionality in parent component to delete selected child instance with check box , I am trying to put a button in parent and when I click that button I should delete the selected rows.
Hi, thank you very much for this.
I was wondering, could you help with providing the code so that this would be inside another component, and therefore all the multiple records would be inserted as related to that object.
Thank you in advance!
Save Functionality is not working. I cant able to save the contact.
Hi,
When user click on + (add) icon new row adding but I need here some functionality after added new row cursor focus need to be on “Firstname” textbox on newly created row. How to do, can you explain and send me sample code.
Thanks,
Anji
Thank you so much for share your costly time with this blogs . And this is very helpful Requirement like when user click on add function icon new row adding ..Great work Heads off you and your Team for help .
Thanks for this, How can I make it work with <lightning:inputField ****/> or <force: inputField***>, I need to use one of these so the input fields respect the field types of an object, for an example a lookup field
It is Excellent post. Thank You!
Excellent post
Hi,
How to limit the row adding, i have the requirement max add rows 20.
Please let me know where should i add the code
Hi,
Please let me know how to control the add row count
we have the requirement, should allow only 20 mix add rows.
Please let me know
it’s very simple you need to check the rowIndex attribute if it is grater then 20 then disable the delete button on component
How to save records successfully even on empty rows.
Hello i am facing problem in saving records, i am unbale to save. please let me know if you have solutions.
Hello ,
i am facing problem in saving records, i am unbale to save. please let me know if you have solutions.
Hi, This is a good Post, we have a requirement to make this component more dyanamic,
depending on parameters we have to create dynamic table and it should have dynamic rows like you already done.
Can you help me in this?
Thanks,
Jyoti
Hi,
This is really a good post.
I want more dynamic functionality in it.
Table should get displayed depending on my configurations and it will have such dyanamic rows as well.
can we have solution for it?
Thanks.
Seems to work great; however, echoing Azar’s question from July 2018, how can we set the AccountId on the newly created Contacts? This seems like a critical element to this functionality.
I figured out how to update the Parent Component to run in a flow and to include an AccountId variable using the Design element, and then I can pass in an Account id from the flow running from the Account page, but how can I take that value I assign to the Parent Component and pass it through to the Contacts being created in the Child Component?
Hello ,
Great post!
I’m facing a problem in saving records though – nothing happening on save – please let me know if you have solution for this.
Thanks