Salesforce Lightning Web Component datatable Validation

Salesforce Lightning Web Component datatable Validation

oncellchange event can be used for cell or column level changes validation.

onsave event can be used used for validating all the values that are updated.

Sample Code:

Apex Class:

public class AccountController {
 
    @AuraEnabled( cacheable = true )
    public static List< Account > fetchAccounts() {
     
        return [ 
            SELECT Id, Name, AccountNumber 
            FROM Account 
            LIMIT 10
        ];
         
    }

    @AuraEnabled
    public static string updateAccounts( Object data ) {
        
        List < Account > accsForUpdate = ( List < Account > ) JSON.deserialize(
            JSON.serialize( data ),
            List < Account >.class
        );
        try {
            update accsForUpdate;
            return 'Success: Account(s) updated successfully';
        }
        catch (Exception e) {
            return 'The following exception has occurred: ' + e.getMessage();
        }

    }
     
}

Lightning Web Component:

HTML:

<template>
    <lightning-card>
        <div class="slds-m-around_medium">
            <lightning-datatable
                    key-field="Id"
                    data={records}
                    columns={columns}
                    hide-checkbox-column
                    draft-values={draftValues}
                    onsave={handleSave}
                    oncellchange={handleCellChange}
                    errors={errors}>
            </lightning-datatable>
        </div>
    </lightning-card>
</template>

JavaScript:

import { LightningElement, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';
import updateAccounts from '@salesforce/apex/AccountController.updateAccounts';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

const COLUMNS = [
    { 
        label: 'Name', 
        fieldName: 'Name', 
        editable: true 
    },
    { 
        label: 'Account Number', 
        fieldName: 'AccountNumber', 
        editable: true 
    }
];

export default class sampleLightningWebComponent extends LightningElement {

    records;
    wiredRecords;
    errors;
    error;
    columns = COLUMNS;
    draftValues = [];

    @wire( fetchAccounts )  
    wiredAccount( value ) {

        this.wiredRecords = value; 
        const { data, error } = value;

        if ( data ) {
                            
            this.records = data;
            this.error = undefined;

        } else if ( error ) {

            this.error = error;
            this.records = undefined;

        }

    }  

    handleCellChange( event ) {

        console.log( 'Inside Handle Cell Change' );
        this.errors = {};
        let changedValue = 
            event.detail.draftValues[ 0 ];
        console.log(
            'Changed Value is',
            JSON.stringify(
                changedValue
            )
        );

        if ( 
            changedValue.hasOwnProperty(
                'Name'
            ) 
        ) {

            console.log(
                'Account Name is',
                changedValue.Name
            );

            if ( 
                changedValue.Name.toLowerCase().includes( 
                    'test' 
                ) 
            ) {

                console.log( 
                    'Id is',
                    changedValue.Id 
                );
                let tempRow = {};
                tempRow[ changedValue.Id ] = {
                    messages: [ 'Please avoid using dummy information in the Account Name' ],
                    fieldNames: [ 'Name' ],
                    title: 'Dummy Information'
                };
                this.errors = {
                    rows: tempRow
                }

            }

        } else if ( 
            changedValue.hasOwnProperty(
                'AccountNumber'
            ) 
        ) {

            console.log(
                'Account Number is',
                changedValue.AccountNumber
            );

            if ( 
                changedValue.AccountNumber.toLowerCase().includes( 
                    'test' 
                ) 
            ) {

                console.log( 
                    'Id is',
                    changedValue.Id 
                );
                let tempRow = {};
                tempRow[ changedValue.Id ] = {
                    messages: [ 'Please avoid using dummy information in the Account Number' ],
                    fieldNames: [ 'AccountNumber' ],
                    title: 'Dummy Information'
                };
                this.errors = {
                    rows: tempRow
                }

            }

        }

    }

    async handleSave( event ) {

        this.errors = {};
        let errorBool = false;
        const updatedFields = event.detail.draftValues;
        let tempRow = {};

        for ( let changedValue of updatedFields ) {

            let errorMessages = [];
            let fieldNames = [];
            
            if ( 
                changedValue.hasOwnProperty(
                    'Name'
                ) 
            ) {
    
                console.log(
                    'Account Name is',
                    changedValue.Name
                );
    
                if ( 
                    changedValue.Name.toLowerCase().includes( 
                        'test' 
                    ) 
                ) {
    
                    errorMessages.push(
                        'Please avoid using dummy information in the Account Name'
                    );
                    fieldNames.push(
                        'Name'
                    );
                    
    
                }
    
            }

            if ( 
                changedValue.hasOwnProperty(
                    'AccountNumber'
                ) 
            ) {
    
                if ( 
                    changedValue.AccountNumber.toLowerCase().includes( 
                        'test' 
                    ) 
                ) {              
                    
                    errorMessages.push(
                        'Please avoid using dummy information in the Account Number'
                    );
                    fieldNames.push(
                        'AccountNumber'
                    );
    
                }
    
            }

            if ( errorMessages.length > 0 ) {

                errorBool = true;
                tempRow[ changedValue.Id ] = {
                    messages: errorMessages,
                    fieldNames: fieldNames,
                    title: 'Error'
                };

            }

        }

        console.log(
            'errorBool is',
            errorBool
        );
        if ( errorBool ) {

            this.errors = {
                rows: tempRow
            }

        } else if ( !errorBool ) {
            
            await updateAccounts( { data: updatedFields } )
            .then( result => {

                console.log( 
                    JSON.stringify( 
                        "Apex update result: " + result 
                    ) 
                );
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Account(s) updated',
                        variant: 'success'
                    })
                );
                
                refreshApex( this.wiredRecords ).then( () => {
                    this.draftValues = [];
                });        

            }).catch( error => {

                console.log( 
                    'Error is ', 
                    JSON.stringify( error ) 
                );
                this.dispatchEvent(
                    new ShowToastEvent( {
                        title: 'Error updating or refreshing records',
                        message: error.body.message,
                        variant: 'error'
                    } )
                );

            });

        }

    }

} 

js-meta.xml:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>59.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>

Output:

Leave a Reply