Thursday, 17 October 2019

Lightning datatable In Lightning Web Components | lightning datatable inline edit

Welcome back, In this post we are going to create another lightning web component (LWC), Where we can search contact records and will display result using lightning-datatable lwc component. Lightning datatable tag is same as lightning:datatable tag in aura. In this lightning Datatable example we will also talk about lightning datatable inline edit.

lighning-datatable syntax:-
                    <lightning-datatable key-field="Id" 
                                            data={contacts} 
                                            columns={columns} 
                                            hide-checkbox-column="true" 
                                            show-row-number-column="true"
                                            > 
                    </lightning-datatable> 
  • If you want to hide the checkbox from table then add "hide-checkbox-column"
  • If you want to show row number then please add "show-row-number-column".
Let's see how we can create custom record search functionality in lightning web components. I hope VsCode is already setup on you machine and you know how to create Lightning Web Component. If not please check this post.

1) Create Apex Class

public with sharing class LWCDataTableExample {
    @AuraEnabled(Cacheable=true)
    public static List <Contact> getContacts(String strLastName) {
        String strLastNameLike = '%'+strLastName+'%';
        List<Contact> contList = [SELECT Id,FirstName,LastName,Account.Name
                                   FROM Contact
                                   Where LastName like :strLastNameLike
                                   LIMIT 10];
        return contList;
    }   
}

This apex class we will call from Lightning web components. If you want to learn more about how to call apex class from lightning web components then please check this post.

2) Create Lightning Web Components.

lwcLightningDataTableDemo.html
<template>
    <lightning-card title = "Search Contacts" icon-name = "custom:custom63"> 
        <div class = "slds-m-around_medium"> 
            <lightning-input type = "search" onchange = {handleKeyChange} class = "slds-m-bottom_small" label = "Search" >
            </lightning-input> 
            <template if:true = {contacts}> 
                <div style="height: 300px;"> 
                    <lightning-datatable key-field="Id" 
                                            data={contacts} 
                                            columns={columns} 
                                            hide-checkbox-column="true" 
                                            show-row-number-column="true"> 
                    </lightning-datatable> 
                </div>                  
            </template>
            <template if:true = {error}> 
                {error}> 
            </template> 
        </div> 
    </lightning-card> 
</template>


lwcLightningDataTableDemo.js
import { LightningElement,track } from 'lwc';
import getContacts from '@salesforce/apex/LWCDataTableExample.getContacts';

const columns = [ 
    { label: 'Id', fieldName: 'Id' }, 
    { label: 'First Name', fieldName: 'FirstName' }, 
    { label: 'Last Name', fieldName: 'LastName' }
];

export default class LwcLightningDataTableDemo extends LightningElement {
    @track contacts;
    @track error; 
    @track columns = columns;
   
    handleKeyChange( event ) { 
        const strLastName = event.target.value; 
        if ( strLastName ) { 
            getContacts( { strLastName } )   
            .then(result => { 
                this.contacts = result; 
                console.log('I am here',this.contacts);
               // console.log(JSON.stringify(result, null, '\t'));
   
            }) 
            .catch(error => { 
                this.error = error; 
            }); 
        } else 
        this.contacts = undefined; 
    }
}

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

</LightningComponentBundle>

NOTE:- Now from Winter 20 release we can Add Lightning Web Components as Custom Tabs for that we need to add lightning__Tab target to the component’s configuration file.

Now Your page will look like this


Lightning datatable inline edit


Let's see how we can do inline Edit
  • For inline editing we can use the uiRecordAPI. For that we need to import the "lightning/uiRecordApi"
  • We also need to add "onsave={handleSave}" and "draft-values={draftValues}"on lightning-datatable and on column we need to add enable "editable: true".
  • Then we need to add handler Save method.

Let's see how our code will look like:


lwcLightningDataTableDemo.html
<template>
    <lightning-card title = "Search Contacts" icon-name = "custom:custom63"> 
        <div class = "slds-m-around_medium"> 
            <lightning-input type = "search" onchange = {handleKeyChange} class = "slds-m-bottom_small" label = "Search" >
            </lightning-input> 
            <template if:true = {contacts}> 
                <div style="height: 300px;"> 
                    <lightning-datatable key-field="Id" 
                                            data={contacts} 
                                            columns={columns} 
                                            hide-checkbox-column="true" 
                                            show-row-number-column="true"
                                            onsave={handleSave}
                                            draft-values={draftValues}
                                            > 
                    </lightning-datatable> 
                </div>                  
            </template>
            <template if:true = {error}> 
                {error}> 
            </template> 
        </div> 
    </lightning-card> 
</template>


lwcLightningDataTableDemo.js
import { LightningElement,track } from 'lwc';
import getContacts from '@salesforce/apex/LWCDataTableExample.getContacts';

import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';


const columns = [ 
    { label: 'Id', fieldName: 'Id' }, 
    { label: 'First Name', fieldName: 'FirstName', editable: true  }, 
    { label: 'Last Name', fieldName: 'LastName', editable: true  }
];

export default class LwcLightningDataTableDemo extends LightningElement {
    @track contacts;
    @track error; 
    @track columns = columns;
    @track draftValues = [];
    handleKeyChange( event ) { 
        const strLastName = event.target.value; 
        if ( strLastName ) { 
            getContacts( { strLastName } )   
            .then(result => { 
                this.contacts = result; 
                // console.log('I am here',this.contacts);
                // console.log(JSON.stringify(result, null, '\t'));
            }) 
            .catch(error => { 
                this.error = error; 
            }); 
        } else 
        this.contacts = undefined; 
    }

    handleSave(event) {
        const recordInputs =  event.detail.draftValues.slice().map(draft => {
            const fields = Object.assign({}, draft);
            return { fields };
        });
   
        const promises = recordInputs.map(recordInput => updateRecord(recordInput));
       
        Promise.all(promises).then(contacts => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'All Contacts updated',
                    variant: 'success'
                })
            );
             // Clear all draft values
             this.draftValues = [];
   
             // Display fresh data in the datatable
             return refreshApex(this.contact);
        }).catch(error => {
            // Handle error
        });
    }


}

Please check below post on Lightning Web Components:-

Check our YouTube Channel for more recording in Lightning Web Components.

Reference :-
1) https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/example
2) https://developer.salesforce.com/docs/component-library/documentation/lwc/data_table_inline_edit


Please share your feedback.

13 comments:

  1. Is there a way to custom css cell/row's background color in lightning:datatable. I need that for conditional highlighting?

    ReplyDelete
  2. after save , record is getting updated but the datatable is not getting updated withe the lastest data

    ReplyDelete
    Replies
    1. Hi Amit,

      Can you please help regarding this? Should I use @wire to call apex method ?

      Thanks
      Suman

      Delete
    2. There could be two reasons,
      refreshApex() refreshes the data that the wire service provisioned. It does not refresh if we call apex method imperatively. That could be one reason.
      and other one is a typo. It should be return refreshApex(this.contacts); there is no contact property associated to result.

      Delete
    3. This comment has been removed by the author.

      Delete
    4. Hello, check this post: https://salesforce.stackexchange.com/questions/318917/how-to-clear-draft-values-in-lwc-datatable-after-save

      It helped-me to solve my problem.

      And I added the following to clear the draftValues.

      After refresh over the provisioned value, I inserted the line: this.draftValues = [];

      Important to say that in the html, also declare in the datatable: draft-values={draftValues}

      Delete
  3. Is there an way to hide row no's from data table?

    ReplyDelete
    Replies
    1. get rid of "show-row-number-column" on lightning-datatable in case you have it and that should solve the problem as by default it is set to No

      Delete
  4. Good post and easy example for iniline editing

    ReplyDelete
  5. I am getting an error. An error occurred while trying to update the record. Please try again.
    Any idea why is this error?

    ReplyDelete
  6. Thanks for sharing your thoughts on %meta_keyword%. Regards

    ReplyDelete
  7. How can we write test class for apex method? I want to pass event.detail.draftValues from test class.

    ReplyDelete
  8. How to display row number as seperate column in datatable

    ReplyDelete