Dynamic Column Validation in LWC Datatables with ES6 Methods
Use case:
To display a list of records in a datatable
with a percentage as one of the columns. The requirement, however, is specific – the sum of all rows in the percentage column must equal 100%, with users allowed to perform inline editing.
While the use case sounds simple, implementing it in LWC presents unique challenges due to how datatable
manages data. The datatable
component uses two key attributes for handling its content:
data
: Holds the initial list of records to display.draftValues
: Stores only the values that have been edited, creating a separate data array that needs to be reconciled with the originaldata
.
We all know there are various ways to address this issue, but I prefer to opt out by utilizing ES6 methods. Let’s divide the solution into three sections:
- Setting up the
datatable
with percentage values. - Handling inline editing using
draftValues
. - Calculating the percentage sum in real-time, ensuring it always equals 100%.
The key to the solution lies in ES6 array methods like map
and reduce
, which allow us to write clean, concise, and efficient code to handle the array manipulations required.
Step-by-Step Implementation
Step 1: Initial Setup of the Datatable Component
First, we initialize the component with data
holding our records and set up the columns with inline editing enabled for the percentage field.
import { LightningElement } from 'lwc';
export default class PercentageDatatable extends LightningElement {
data = [
{ id: '1', name: 'Record A', percentage: 20 },
{ id: '2', name: 'Record B', percentage: 30 },
{ id: '3', name: 'Record C', percentage: 50 }
];
columns = [
{ label: 'Name', fieldName: 'name', type: 'text' },
{
label: 'Percentage',
fieldName: 'percentage',
type: 'number',
editable: true
}
];
draftValues = [];
}
In this setup:
data
contains the original records.columns
defines the structure, withpercentage
set as an editable field.draftValues
will store the inline-edited values.
Step 2: Handling Inline Edit Changes
We add an event handler to track the inline changes. Whenever a user edits a percentage value, we capture the new values in draftValues
.
handleSave(event) {
// Capture edited values
this.draftValues = event.detail.draftValues;
// Merge draftValues with the original data to get updated records
const updatedData = this.data.map(record => {
const draft = this.draftValues.find(d => d.id === record.id);
return draft ? { ...record, ...draft } : record;
});
// Calculate the total percentage <3
const totalPercentage = updatedData.reduce((sum, record) => sum + parseFloat(record.percentage || 0), 0);
if (totalPercentage === 100) {
// Success case: total percentage equals 100
this.data = updatedData;
this.draftValues = [];
// You may also want to show a success message to the user
} else {
// Error case: percentages do not add up to 100
this.showErrorMessage('The total percentage must equal 100%.');
}
}
In this code:
- We use a
map
to combinedraftValues
with the originaldata
, ensuring we consider both the original and edited values. - We use
reduce
to calculate the total percentage by summing up thepercentage
values across all records.
Step 3: Displaying Error Messages
When the percentage sum does not equal 100, we provide feedback to the user to correct the values.
// throw an error using toast event
showErrorMessage(message) {
const errorEvent = new ShowToastEvent({
title: 'Error',
message: message,
variant: 'error',
});
this.dispatchEvent(errorEvent);
}
Using ShowToastEvent
, we display an error message if the total percentage deviates from 100%, prompting the user to adjust their entries accordingly.
Implementing the 100% validation for a percentage column in Salesforce LWC datatable
with inline editing required a strategic approach to handling data
and draftValues
arrays. By leveraging ES6 methods like map
and reduce
, we efficiently merged these arrays and calculated the total percentage in just a few lines of readable and maintainable code.
Here's the complete JavaScript code for reference: