Thursday, July 4, 2019

Lightning DataTable With Row Actions in Lightning Web Component(lwc)

This post explains how to handle row actions in the lightning data table in lightning web components(lwc)



Example:
HTML Code
<template>
     <lightning-card title="Datatable with Row Actions" icon-name="standard:contact" > <br/>
        <div style="width: auto;">
            <template if:true={data}>

                <lightning-datatable data={data}
                                     columns={columns}
                                     key-field="id"
                                     hide-checkbox-column="true"
                                     onrowaction={handleRowActions}></lightning-datatable>
            </template>

        </div>

        <!-- Spinner -->
        <div if:true={showLoadingSpinner}>
            <lightning-spinner alternative-text="Loading" size="large"></lightning-spinner>
        </div>

        <!-- Detail view modal -->
        <template if:true={bShowModal}>
            <section role="dialog" tabindex="-1"
                    aria-labelledby="modal-heading-01"
                    aria-modal="true"
                    aria-describedby="modal-content-id-1"
                    class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <!-- modal header -->
                <header class="slds-modal__header">
                    <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
                        <lightning-icon icon-name="utility:close" alternative-text="close" variant="inverse" size="small" ></lightning-icon>
                    </button>
                    
                    <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate" if:false={isEditForm}>Record Detail</h2>
                    <h2 id="modal-heading-02" class="slds-text-heading_medium slds-hyphenate" if:true={isEditForm}>Update Record Values</h2>
                </header>
                <!-- modal body -->
                <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1" if:false={isEditForm}>
                    <dl class="slds-list_horizontal slds-wrap">
                        <dt class="slds-item_label slds-truncate" title="First Name">First Name:</dt>
                        <dd class="slds-item_detail slds-truncate">{record.FirstName}</dd>
                        <dt class="slds-item_label slds-truncate" title="LastName">Last Name:</dt>
                        <dd class="slds-item_detail slds-truncate">{record.LastName}</dd>
                        <dt class="slds-item_label slds-truncate" title="Phone">Phone :</dt>
                        <dd class="slds-item_detail slds-truncate"><lightning-formatted-phone value={record.Phone} ></lightning-formatted-phone></dd>
                        <dt class="slds-item_label slds-truncate" title="Email">Email :</dt>
                        <dd class="slds-item_detail slds-truncate"><lightning-formatted-email value={record.Email} ></lightning-formatted-email></dd>
                    </dl>
                </div>
                
                <!-- showing record edit form -->
                <div if:true={isEditForm} class="slds-theme_default">
                    <lightning-record-edit-form layout-type="Full" record-id={currentRecordId} object-api-name="Contact" onsubmit={handleSubmit} onsuccess={handleSuccess}>
                        <lightning-messages></lightning-messages>
                        <lightning-output-field field-name="AccountId"></lightning-output-field>
                        <lightning-input-field field-name="FirstName"></lightning-input-field>
                        <lightning-input-field field-name="LastName"></lightning-input-field>
                        <lightning-input-field field-name="Email"></lightning-input-field>
                        <lightning-input-field field-name="Phone"></lightning-input-field><br/>
                        
                        <div style="text-align:center;">
                            <lightning-button class="slds-m-top_small"
                                              variant="brand"
                                              type="submit"
                                              name="update"
                                              label="Update Record"></lightning-button>
                        </div>
                    </lightning-record-edit-form><br/>
                    <div></div>
                </div>

                <!-- modal footer start-->
                <footer class="slds-modal__footer" if:false={isEditForm}>
                    <lightning-button variant="brand"
                                      label="Close"
                                      title="Close"
                                      onclick={closeModal}></lightning-button>
                </footer>
            </div>
            </section>
            <div class="slds-backdrop slds-backdrop_open"></div>
           
        </template>
    </lightning-card>   
</template>
Javascript controller code
import {LightningElement, track, wire} from 'lwc';

// importing apex class methods
import getContacts from '@salesforce/apex/LWCExampleController.getContacts';
import delSelectedCons from '@salesforce/apex/LWCExampleController.deleteContacts';

// importing to show toast notifictions
import {ShowToastEvent} from 'lightning/platformShowToastEvent';

// importing to refresh the apex if any record changes the datas
import {refreshApex} from '@salesforce/apex';

// row actions
const actions = [
    { label: 'Record Details', name: 'record_details'}, 
    { label: 'Edit', name: 'edit'}, 
    { label: 'Delete', name: 'delete'}
];

// datatable columns with row actions
const columns = [
    { label: 'FirstName', fieldName: 'FirstName' }, 
    { label: 'LastName', fieldName: 'LastName' },
    { label: 'Phone', fieldName: 'Phone', type: 'phone'}, 
    { label: 'Email', fieldName: 'Email', type: 'email' }, 
    {
        type: 'action',
        typeAttributes: {
            rowActions: actions,
            menuAlignment: 'right'
        }
    }
];

export default class DeleteRowsInDatatableLWC extends LightningElement { 
    // reactive variable
    @track data;
    @track columns = columns;
    @track record = [];
    @track bShowModal = false;
    @track currentRecordId;
    @track isEditForm = false;
    @track showLoadingSpinner = false;

    // non-reactive variables
    selectedRecords = [];
    refreshTable;
    error;

    // retrieving the data using wire service
    @wire(getContacts)
    contacts(result) {
        this.refreshTable = result;
        if (result.data) {
            this.data = result.data;
            this.error = undefined;

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

    handleRowActions(event) {
        let actionName = event.detail.action.name;

        window.console.log('actionName ====> ' + actionName);

        let row = event.detail.row;

        window.console.log('row ====> ' + row);
        // eslint-disable-next-line default-case
        switch (actionName) {
            case 'record_details':
                this.viewCurrentRecord(row);
                break;
            case 'edit':
                this.editCurrentRecord(row);
                break;
            case 'delete':
                this.deleteCons(row);
                break;
        }
    }

    // view the current record details
    viewCurrentRecord(currentRow) {
        this.bShowModal = true;
        this.isEditForm = false;
        this.record = currentRow;
    }

    // closing modal box
    closeModal() {
        this.bShowModal = false;
    }


    editCurrentRecord(currentRow) {
        // open modal box
        this.bShowModal = true;
        this.isEditForm = true;

        // assign record id to the record edit form
        this.currentRecordId = currentRow.Id;
    }

    // handleing record edit form submit
    handleSubmit(event) {
        // prevending default type sumbit of record edit form
        event.preventDefault();

        // querying the record edit form and submiting fields to form
        this.template.querySelector('lightning-record-edit-form').submit(event.detail.fields);

        // closing modal
        this.bShowModal = false;

        // showing success message
        this.dispatchEvent(new ShowToastEvent({
            title: 'Success!!',
            message: event.detail.fields.FirstName + ' '+ event.detail.fields.LastName +' Contact updated Successfully!!.',
            variant: 'success'
        }),);

    }

    // refreshing the datatable after record edit form success
    handleSuccess() {
        return refreshApex(this.refreshTable);
    }

    deleteCons(currentRow) {
        let currentRecord = [];
        currentRecord.push(currentRow.Id);
        this.showLoadingSpinner = true;

        // calling apex class method to delete the selected contact
        delSelectedCons({lstConIds: currentRecord})
        .then(result => {
            window.console.log('result ====> ' + result);
            this.showLoadingSpinner = false;

            // showing success message
            this.dispatchEvent(new ShowToastEvent({
                title: 'Success!!',
                message: currentRow.FirstName + ' '+ currentRow.LastName +' Contact deleted.',
                variant: 'success'
            }),);

            // refreshing table data using refresh apex
             return refreshApex(this.refreshTable);

        })
        .catch(error => {
            window.console.log('Error ====> '+error);
            this.dispatchEvent(new ShowToastEvent({
                title: 'Error!!', 
                message: error.message, 
                variant: 'error'
            }),);
        });
    }

}

Configuration XML File
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="DeleteRowsInDatatableLWC">
    <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, FirstName,LastName, Phone, Email FROM Contact ORDER BY Name limit 10];
    }
    
    @AuraEnabled
    public static void deleteContacts(list<Id> lstConIds){
        try {
            list<Contact> lstConsToDelete = new list<Contact>();
            System.debug('lstConIds ====> '+lstConIds);
            for(Id idCon : lstConIds) {
                lstConsToDelete.add(new Contact(Id = idCon));
            }
            if(!lstConsToDelete.isEmpty()) {
                delete lstConsToDelete;
            }
        }
        catch(Exception ex) {
            throw new AuraHandledException(ex.getMessage());
        }
    }
}
Result:

Resources:
lightning-datatable
record-edit-form

7 comments:

  1. It appears that the screenshot implies that these contacts belong to the account being viewed. I expected the getContacts() method then to return a list but accept a string -> the account.id to use in the query. That does not appear here...am I missing something?

    ReplyDelete
  2. Thank you so much for this example! It was easy to replicate and it works exactly as expected.

    ReplyDelete
  3. how drag and drop lightning Datatable column in lightning component
    please give some idea

    ReplyDelete
  4. Thank-you very much, this was really informative and helpful.

    ReplyDelete
  5. How can we create the new record using the new button in data table?

    ReplyDelete