Showing posts with label lightning-datatable. Show all posts
Showing posts with label lightning-datatable. Show all posts

Tuesday, December 15, 2020

Inline Editing in lightning-datatable in Salesforce Lightning Web Component(lwc)

 This post explains, inline editing in lightning-datatable in salesforce lightning web components(lwc).


HTML Code:

<template>
    <lightning-card title="Inline Edit With Lightning Datatable in LWC">
        <template if:true={contacts.data}>
            <lightning-datatable key-field="Id" 
                                 data={contacts.data} 
                                 columns={columns} 
                                 onsave={handleSave}
                                 draft-values={saveDraftValues} 
                                 hide-checkbox-column 
                                 show-row-number-column>
            </lightning-datatable>
        </template>
    </lightning-card>
</template>


Javascript Code:

import { LightningElement, wire, track } from 'lwc';
import getContacts from '@salesforce/apex/LWCExampleController.getContacts';
import { updateRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { refreshApex } from '@salesforce/apex';
// datatable columns
const columns = [
    {
        label: 'Name',
        fieldName: 'Name',
        type: 'text',
    }, {
        label: 'FirstName',
        fieldName: 'FirstName',
        type: 'text',
        editable: true,
    }, {
        label: 'LastName',
        fieldName: 'LastName',
        type: 'text',
        editable: true,
    }, {
        label: 'Phone',
        fieldName: 'Phone',
        type: 'phone',
        editable: true
    }
];

export default class InlineEditTable extends LightningElement {

    columns = columns;
    @track contacts;
    saveDraftValues = [];

    @wire(getContacts)
    cons(result) {
        this.contacts = result;
        if (result.error) {
            this.contacts = undefined;
        }
    };

    handleSave(event) {
        this.saveDraftValues = event.detail.draftValues;
        const recordInputs = this.saveDraftValues.slice().map(draft => {
            const fields = Object.assign({}, draft);
            return { fields };
        });

        // Updateing the records using the UiRecordAPi
        const promises = recordInputs.map(recordInput => updateRecord(recordInput));
        Promise.all(promises).then(res => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Records Updated Successfully!!',
                    variant: 'success'
                })
            );
            this.saveDraftValues = [];
            return this.refresh();
        }).catch(error => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error',
                    message: 'An Error Occured!!',
                    variant: 'error'
                })
            );
        }).finally(() => {
            this.saveDraftValues = [];
        });
    }

    // This function is used to refresh the table once data updated
    async refresh() {
        await refreshApex(this.contacts);
    }
}

Apex Code:

public inherited sharing class LWCExampleController {

    @AuraEnabled(Cacheable = true)
    public static List<Contact> getContacts() {
        return [SELECT Id, Name, FirstName, LastName, Phone, Email 
                FROM Contact 
                WHERE Email != null 
                AND Phone != null 
                ORDER BY CreatedDate DESC NULLS LAST limit 10];
    }
}


Output:



Friday, July 5, 2019

Lightning Data table with sorting in Lightning Web Component(lwc)

This post explains how to sort the lightning data table data in lightning web components(lwc)



Example:
HTML Code
<template>
    <lightning-card title="Sorting Data in Lightning Datatable in LWC" icon-name="standard:contact" > <br/>
        <div style="width: auto;">
            <template if:true={data}>
                <lightning-datatable data={data}
                                     columns={columns}
                                     key-field="id"
                                     sorted-by={sortBy}
                                     sorted-direction={sortDirection}
                                     onsort={handleSortdata}
                                     hide-checkbox-column="true"></lightning-datatable>
            </template>

        </div>
    </lightning-card>
</template>
Javascript Controller Code
import {LightningElement, wire, track} from 'lwc';

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

// datatable columns with row actions
const columns = [
    {
        label: 'FirstName',
        fieldName: 'FirstName',
        sortable: "true"
    }, {
        label: 'LastName',
        fieldName: 'LastName',
        sortable: "true"
    }, {
        label: 'Phone',
        fieldName: 'Phone',
        type: 'phone',
        sortable: "true"
    }, {
        label: 'Email',
        fieldName: 'Email',
        type: 'email'
    },
];

export default class DataTableWithSortingInLWC extends LightningElement { 
    // reactive variable
    @track data;
    @track columns = columns;
    @track sortBy;
    @track sortDirection;

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

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

    handleSortdata(event) {
        // field name
        this.sortBy = event.detail.fieldName;

        // sort direction
        this.sortDirection = event.detail.sortDirection;

        // calling sortdata function to sort the data based on direction and selected field
        this.sortData(event.detail.fieldName, event.detail.sortDirection);
    }

    sortData(fieldname, direction) {
        // serialize the data before calling sort function
        let parseData = JSON.parse(JSON.stringify(this.data));

        // Return the value stored in the field
        let keyValue = (a) => {
            return a[fieldname];
        };

        // cheking reverse direction 
        let isReverse = direction === 'asc' ? 1: -1;

        // sorting data 
        parseData.sort((x, y) => {
            x = keyValue(x) ? keyValue(x) : ''; // handling null values
            y = keyValue(y) ? keyValue(y) : '';

            // sorting values based on direction
            return isReverse * ((x > y) - (y > x));
        });

        // set the sorted data to data table data
        this.data = parseData;

    }

}
Configuration XML File

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="dataTableWithSortingInLWC">
    <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 limit 15];
    }
}
Result

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

Friday, June 28, 2019

How to Delete multiple selected records in Lightning Datatable in lightning web components(lwc)

This post explains how to delete multiple selected records in lightning datatable in lightning web components(lwc)



Example
deleteRowsInDatatableLWC.html
<template>
     <lightning-card title="Delete Selected Rows in Datatable" icon-name="standard:contact" > <br/>
        <div style="width: auto;">
            <template if:true={data}>
                    <div class="slds-grid slds-gutters">
                            <div class="slds-col">
                              <span><p style="margin-left: 5%">Selected Records: <b style="color:red;">{recordsCount}</b></p></span>
                            </div>
                            <div class="slds-col">
                                <span>                    
                                    <lightning-button label={buttonLabel}
                                                      icon-name="utility:delete"
                                                      disabled={isTrue}
                                                      variant="destructive" 
                                                      onclick={deleteAccounts}
                                                      style="margin-left: 40%"></lightning-button>
                                </span>
                            </div>
                        </div><br/>

                    <lightning-datatable data={data}
                                     columns={columns}
                                     key-field="id"
                                     onrowselection={getSelectedRecords}></lightning-datatable>
            </template>

        </div>
    </lightning-card>   
</template>
deleteRowsInDatatableLWC.js
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 after delete the records.
import {refreshApex} from '@salesforce/apex';

// datatable columns
const columns = [
    {
        label: 'FirstName',
        fieldName: 'FirstName'
    }, {
        label: 'LastName',
        fieldName: 'LastName'
    }, {
        label: 'Phone',
        fieldName: 'Phone',
        type: 'phone'
    }, {
        label: 'Email',
        fieldName: 'Email',
        type: 'email'
    }
];

export default class DeleteRowsInDatatableLWC extends LightningElement {
    // reactive variable
    @track data;
    @track columns = columns;
    @track buttonLabel = 'Delete Selected Contacts';
    @track isTrue = false;
    @track recordsCount = 0;

    // 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;
        }
    }


    // Getting selected rows 
    getSelectedRecords(event) {
        // getting selected rows
        const selectedRows = event.detail.selectedRows;
        
        this.recordsCount = event.detail.selectedRows.length;

        // this set elements the duplicates if any
        let conIds = new Set();

        // getting selected record id
        for (let i = 0; i < selectedRows.length; i++) {
            conIds.add(selectedRows[i].Id);
        }

        // coverting to array
        this.selectedRecords = Array.from(conIds);

        window.console.log('selectedRecords ====> ' +this.selectedRecords);
    }


    // delete records process function
    deleteAccounts() {
        if (this.selectedRecords) {
            // setting values to reactive variables
            this.buttonLabel = 'Processing....';
            this.isTrue = true;

            // calling apex class to delete selected records.
            this.deleteCons();
        }
    }


    deleteCons() {
        delSelectedCons({lstConIds: this.selectedRecords})
        .then(result => {
            window.console.log('result ====> ' + result);

            this.buttonLabel = 'Delete Selected Contacts';
            this.isTrue = false;

            // showing success message
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success!!', 
                    message: this.recordsCount + ' Contacts are deleted.', 
                    variant: 'success'
                }),
            );
            
            // Clearing selected row indexs 
            this.template.querySelector('lightning-datatable').selectedRows = [];

            this.recordsCount = 0;

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

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

}
deleteRowsInDatatableLWC.js-meta.xml
<?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());
        }
    }
}
Output