Adding or Removing rows DYNAMICALLY in Lightning web component

Are you looking for adding or removing rows dynamically in Lightning Web Component to create records or do something else? In this blog, I am going to demonstrate adding or removing rows dynamically to create Contact records in bulk using Lightning Data Service. You will also learn accessing the html element and access public methods of those html elements.

Business use case

Your team wants an ability to add contacts in bulk in one go by using adding or removing rows dynamically. The standard New Contact button in Salesforce gives you the ability to add one at a time and its time consuming.

Implementation – adding or removing rows dynamically

Let’s create a custom Lightning Web Component in our Visual Studio Code. Create a Lightning Web Component with name “dynamicRecordCreationRows“.The Lightning Web Component will have generally three files. They are html, js and meta-xml.js.

ADD/REMOVE ROWS DYNAMICALLY IN LIGHTNING WEB COMPONENT

dynamicRecordCreationRows.html

The html file has used for:each iterator to iterator over the array controlled by button to add or remove rows in each rows. The input fields which are part of lighting-record-edit-form placed in lightning-layout component. A lightning-layout is a flexible grid system for arranging containers within a page or inside another container. The default layout is mobile-first and can be easily configured to work on different devices. To understand these concepts in a better way, check these links:-

  1. Render Lists
  2. lightning-layout
  3. Layout Item
  4. lightning-record-edit-form
  5. lightning-input-field
ADD/REMOVE ROWS DYNAMICALLY IN LIGHTNING WEB COMPONENT
<template>
    <lightning-card>
        <h3 slot="title">
            <lightning-icon icon-name="standard:timesheet" alternative-text="Event" size="small"></lightning-icon>
            &nbsp;Bulk Contact Creation
        </h3>
        <template for:each={itemList} for:item="item" for:index="index">
            <lightning-record-edit-form key={item.id} object-api-name="Contact">
                <lightning-messages> </lightning-messages>
                <lightning-layout multiple-rows>
                    <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="2"
                        padding="around-small">
                        <lightning-input-field field-name="FirstName" variant="label-stacked" required>
                        </lightning-input-field>
                    </lightning-layout-item>
                    <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="2"
                        padding="around-small">
                        <lightning-input-field field-name="LastName" variant="label-stacked" required>
                        </lightning-input-field>
                    </lightning-layout-item>
                    <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="2"
                        padding="around-small">
                        <lightning-input-field field-name="Title" variant="label-stacked" required>
                        </lightning-input-field>
                    </lightning-layout-item>
                    <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="2"
                        padding="around-small">
                        <lightning-input-field field-name="Email" variant="label-stacked" required>
                        </lightning-input-field>
                    </lightning-layout-item>
                    <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="2"
                        padding="around-small">
                        <lightning-input-field field-name="AccountId" variant="label-stacked" required>
                        </lightning-input-field>
                    </lightning-layout-item>
                    <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="2"
                        padding="around-small">
                        <div class="slds-p-top_medium">
                            <lightning-icon icon-name="action:new" access-key={item.id} id={index}
                                alternative-text="Add Row" size="small" title="Add Row" onclick={addRow}>
                            </lightning-icon>
                            <lightning-icon icon-name="action:delete" access-key={item.id} id={index}
                                alternative-text="Delete Row" size="small" title="Delete Row" onclick={removeRow}>
                            </lightning-icon>
                        </div>
                    </lightning-layout-item>
                </lightning-layout>

            </lightning-record-edit-form>
        </template>
        </br>
        <lightning-layout>
            <div class="slds-align_absolute-center">
                <lightning-button variant="success" onclick={handleSubmit} name="submit" label="Submit">
                </lightning-button>
            </div>
        </lightning-layout>
    </lightning-card>
</template>

dynamicRecordCreationRows.js

The JavaScript file of the component has the method defined to handle the button click. We have three methods defined each for adding rows, removing rows and saving records.

  1. addRow – This method adds an value using concat method to the array so that rows gets added.
  2. removeRow – This method removes the value using array filter method. As a result, the rows gets removed.
  3. handleSubmit – This methods first validates the input fields and then insert the records using Lightning Data Service submit() method.
import { LightningElement, track } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class DynamicRecordCreationRows extends NavigationMixin(LightningElement) {

    keyIndex = 0;
    @track itemList = [
        {
            id: 0
        }
    ];

    addRow() {
        ++this.keyIndex;
        var newItem = [{ id: this.keyIndex }];
        this.itemList = this.itemList.concat(newItem);
    }

    removeRow(event) {
        if (this.itemList.length >= 2) {
            this.itemList = this.itemList.filter(function (element) {
                return parseInt(element.id) !== parseInt(event.target.accessKey);
            });
        }
    }

    handleSubmit() {
        var isVal = true;
        this.template.querySelectorAll('lightning-input-field').forEach(element => {
            isVal = isVal && element.reportValidity();
        });
        if (isVal) {
            this.template.querySelectorAll('lightning-record-edit-form').forEach(element => {
                element.submit();
            });
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Contacts successfully created',
                    variant: 'success',
                }),
            );
            // Navigate to the Account home page
            this[NavigationMixin.Navigate]({
                type: 'standard__objectPage',
                attributes: {
                    objectApiName: 'Contact',
                    actionName: 'home',
                },
            });
        } else {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error creating record',
                    message: 'Please enter all the required fields',
                    variant: 'error',
                }),
            );
        }
    }

}

dynamicRecordCreationRows.js-meta.xml

The meta file defines the metadata of the component like where it can be used. In our case, we have exposed the component to be used with Home, Record and App page in Lightning Experience.

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Demoadding or removing rows dynamically

Leave a Reply