This post explains how to implement custom data table with multiple row selection in Lightning Web Component(lwc)
customDatatableInLWC.html
customDatatableInLWC.js
customDatatableInLWC.js-meta.xml
Apex Class
Result
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
Thanks it helped me lot.
ReplyDeletethis can be done with standard datatable.
ReplyDeletenot much dude
ReplyDeleteHi ,
ReplyDeleteCan 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
Very Helpful
ReplyDeleteThis 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