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: