Thursday, October 17, 2019

Custom Data table with multiple row selection in Lightning Web Components(lwc)

This post explains how to implement custom data table with multiple row selection in Lightning Web Component(lwc)



customDatatableInLWC.html
<template>
    <lightning-card title="Custom Data table in Lightning Web Components">
        <div class="slds-grid slds-gutters">
            <div class="slds-col">
                <span></span>
            </div>
            <div class="slds-col">
                <span>
                    <lightning-button label="Show Selected Contacts" onclick={showContacts} style="margin-left: 40%" variant="brand"></lightning-button>
                </span>
            </div>
        </div><br/>
        <table class="slds-table slds-table_cell-buffer slds-table_bordered">
            <thead>
                <tr class="slds-line-height_reset">
                    <th class="" scope="col">
                        <div class="slds-truncate">
                            <lightning-input onchange={allSelected} type="checkbox"></lightning-input>
                        </div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Name">Name</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="First Name">First Name</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Last Name">Last Name</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Phone">Phone</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Email">Email</div>
                    </th>
                </tr>
            </thead>
            <tbody>
                <template for:each={data} for:item="con">
                    <tr key={con.Id}>
                        <th scope="col">
                            <div>
                                <lightning-input type="checkbox" value={con.Name} data-id={con.Id}></lightning-input>
                            </div>
                        </th>
                        <th scope="col">
                            <div>{con.Name}</div>
                        </th>
                        <th scope="col">
                            <div>{con.FirstName}</div>
                        </th>
                        <th scope="col">
                            <div>{con.LastName}</div>
                        </th>
                        <th scope="col">
                            <div>
                                <lightning-formatted-phone value={con.Phone}></lightning-formatted-phone>
                            </div>
                        </th>
                        <th scope="col">
                            <div>
                                <lightning-formatted-email value={con.Email}></lightning-formatted-email>
                            </div>
                        </th>
                    </tr>
                </template>
            </tbody>
        </table>

        <!--
            This modal box used to show the selected contacts
        -->

        <div if:true={selectedCons}>
            <template if:true={bShowModal}>
                <section aria-describedby="modal-content-id-1" aria-labelledby="modal-heading-01" aria-modal="true" class="slds-modal slds-fade-in-open" role="dialog" tabindex="-1">
                    <div
                        class="slds-modal__container">
                        <!-- modal header start -->
                        <header class="slds-modal__header">
                            <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" onclick={closeModal} title="Close">
                                <lightning-icon alternative-text="close" icon-name="utility:close" size="small" variant="inverse"></lightning-icon>
                                <span class="slds-assistive-text">Close</span>
                            </button>
                            <h2 class="slds-text-heading_medium slds-hyphenate" id="modal-heading-01">Selected Contacts Records</h2>
                        </header>
                        <!-- modal body start -->
                        <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                            <template for:each={selectedCons} for:item="con">
                                <dl class="slds-list_horizontal slds-wrap" if:true={con.Id} key={con.Id}>
                                    <dt class="slds-item_label slds-truncate" title="First Name">Contact Name:</dt>
                                    <dd class="slds-item_detail slds-truncate">{con.Name}</dd>
                                    <dt class="slds-item_label slds-truncate" title="LastName">Contact Id:</dt>
                                    <dd class="slds-item_detail slds-truncate">{con.Id}</dd>
                                    <hr></dl>
                                </template>

                            </div>
                            <!-- modal footer start-->
                            <footer class="slds-modal__footer">
                                <button class="slds-button slds-button_neutral" onclick={closeModal}>Cancel</button>
                            </footer>
                        </div>
                    </section>
                    <div class="slds-backdrop slds-backdrop_open"></div>
                </template>
            </div>
        </lightning-card>
    </template>

customDatatableInLWC.js
import { LightningElement, track, wire } from 'lwc';

// importing Apex Class
import retriveCons from '@salesforce/apex/LWCExampleController.getContacts';

export default class CustomHTMLDatatable extends LightningElement {
    // reactive variables
    @track data = [];
    @track error;
    @track bShowModal = false;
    @track selectedCons;

    // opening the modal
    openModal() { this.bShowModal = true; }
    // closeing the modal
    closeModal() { this.bShowModal = false;}

    // Getting Contacts using Wire Service
    @wire(retriveCons)
    contacts(result) {
        if (result.data) {
            this.data = result.data;
            this.error = undefined;

        } else if (result.error) {
            this.error = result.error;
            this.data = undefined;
        }
    }

    // Select the all rows
    allSelected(event) {
        let selectedRows = this.template.querySelectorAll('lightning-input');
        
        for(let i = 0; i < selectedRows.length; i++) {
            if(selectedRows[i].type === 'checkbox') {
                selectedRows[i].checked = event.target.checked;
            }
        }
    }

    showContacts() {
        this.bShowModal = true;

        this.selectedCons = [];

        let selectedRows = this.template.querySelectorAll('lightning-input');

        // based on selected row getting values of the contact
        for(let i = 0; i < selectedRows.length; i++) {
            if(selectedRows[i].checked && selectedRows[i].type === 'checkbox') {
                this.selectedCons.push({
                    Name: selectedRows[i].value,
                    Id: selectedRows[i].dataset.id
                })
            }
        }
    }

}

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


Apex Class
public inherited sharing class LWCExampleController {    
 @AuraEnabled(Cacheable = true)
    public static List<Contact> getContacts(){
        return [SELECT Id, Name, FirstName,LastName, Phone, Email FROM Contact limit 10];
    }
}

Result



6 comments:

  1. this can be done with standard datatable.

    ReplyDelete
  2. Hi ,
    Can you please help help me this.
    When I check all from header and deselect a row the table . The header select is not getting deselected
    Thank you in Advance

    ReplyDelete
  3. This post was helpful. Thank you. However, i have another question in this, when we implement pagination, how do we persist the row selection while navigating to pages?

    ReplyDelete