Sept 27, 2024
In this blog we will learn how to add actions in lightning datatable. To add Edit and Delete button for operation we have to create Static Row-Level actions. A row-level action provide facility of perform action on table row of data. Such as updating and deleting the table row. Static actions apply to all rows on the table. You can do actions on each row and handle them using the onrowaction
event handler.
There are below action inside lightning datatable:
a) Static Row-Level Actions
b) Dynamic Row-Level Actions
But in this blog we used only Static Row-Level Actions.
label = Required. The label that's displayed for the action.
name = Required. The name of the action, which identifies the selected action.
disabled = Specifies whether the action can be selected. If true, the action item is shown as disabled. This value defaults to false.
iconName = The name of the icon to be displayed to the right of the action item.
Let's jump to the code.
<template>
<div style="width: 100%;">
<lightning-datatable
data-id="datatable"
key-field="Id"
data={data}
columns={columns}
min-column-width="150"
max-column-width="800"
onrowaction={handleRowAction}
</lightning-datatable>
</div>
</template>
import { LightningElement, wire } from 'lwc';
import retrieveAccounts from '@salesforce/apex/TableController.retrieveAccounts';
import { refreshApex } from "@salesforce/apex";
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { updateRecord, deleteRecord } from 'lightning/uiRecordApi';
import EditModal from 'c/editModal';
import LightningConfirm from 'lightning/confirm';
import { reduceErrors } from 'c/ldsUtils';
const actions = [
{ label: 'Edit', name: 'edit' },
{ label: 'Delete', name: 'delete' },
];
const columns = [
{ label: 'Name', fieldName: 'Name'},
{ label: 'Type', fieldName: 'Type' },
{ label: 'Amount', fieldName: 'Amount__c' },
{ label: 'Email__c', fieldName: 'Email__c' },
{ label: 'Industry', fieldName: 'Industry' },
{ type: 'action', typeAttributes: { rowActions: actions }}
];
export default class LightningDatatable extends LightningElement {
columns = columns;
data;
wiredActivities
@wire(retrieveAccounts)
wiredAccounts(value) {
this.wiredActivities = value;
const {data, error} = value;
if (data) {
this.data = data;
} else if (error) {
console.log(error);
}
}
handleRowAction(event) { //Invoke when click on Edit or Delete button
const actionName = event.detail.action.name;
const row = event.detail.row;
switch (actionName) {
case 'edit':
this.editRow(row);
break;
case 'delete':
this.deleteRow(row);
break;
default:
}
}
editRow(row) {
EditModal.open({
recordId: row.Id,
label: `Edit ${row.Name}`,
size: 'small',
description: 'Edit the account',
rowdata: row,
onupdate: (e) => {
//stop further propagation of the event
e.stopPropagation();
this.handleUpdate(e.detail); //Getting the changed values from editModal component.
}
})
}
async handleUpdate(detail) {
const recordUpdatePromises = detail.map((record) => updateRecord(record)); //Then passed the data for udpate to updateRecord method of uiRecordApi.
let promise = await Promise.all(recordUpdatePromises);
if(promise) {
refreshApex(this.wiredActivities); //See changes after update the record.
this.showToast('Success', 'Account updated', 'success');
}
}
async deleteRow(row) {
const recordId = row.Id;
try {
const response = await this.handleConfirmClick();
if(response) {
await deleteRecord(recordId); //Passed the data for delete to deleteRecord method of uiRecordApi.
refreshApex(this.wiredActivities); //See changes after delete the record.
this.showToast('Success', 'Account deleted', 'success');
}
} catch (error) {
this.showToast('Error deleting record', reduceErrors(error).join(', '), 'error');
}
}
async handleConfirmClick() {
const result = await LightningConfirm.open({
message: 'Are you sure you want to delete this account?',
variant: 'header',
label: 'Delete Account',
theme: 'error'
});
return result;
}
showToast(title, msg, error) {
const toastEvent = new ShowToastEvent({
title: title,
message: msg,
variant: error,
mode: 'dismissible'
})
this.dispatchEvent(toastEvent);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>61.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__HomePage</target>
<target>lightning__RecordPage</target>
</targets>
</LightningComponentBundle>
The lightning-record-edit-form component creates a form that adds or updates Salesforce records. It shows fields with their labels and values, and lets you edit them. lightning-record-edit-form supports the following features.
To specify editable fields, use lightning-input-field components inside lightning-record-edit-form component. See the Editing a Record section. External objects are not supported. The InformalName field is not supported for editing. For see the support object go to Support Object.
To edit records, provide the recordId
and object API
name. Use lightning-input-field to choose the fields to edit. Include a lightning-button with type="submit" to validate fields and submit changes. lightning-record-edit-form uses a button for form submission. You can't customize the form element for submission. Use lightning-button with type="submit" as explained before. The default type on lightning-button is button, which does nothing unless you use an onclick handler. If you use an HTML button element within lightning-record-edit-form, the default is type="submit".
<template>
<lightning-modal-header label={label}></lightning-modal-header>
<lightning-modal-body>
<lightning-record-edit-form record-id={recordId} object-api-name="Account" onsubmit={updateModal} >
<lightning-messages> </lightning-messages>
<template for:each={data} for:item="item">
<div key={item.Id}>
<lightning-layout>
<lightning-layout-item size="6">
<lightning-input-field name="Name" field-name="Name" value={item.Name}> </lightning-input-field>
<lightning-input-field name="Type" field-name="Type" value={item.Type}> </lightning-input-field>
<lightning-input-field name="Amount__c" field-name="Amount__c" value={item.Amount__c}> </lightning-input-field>
</lightning-layout-item>
<lightning-layout-item size="6">
<lightning-input-field name="Email__c" field-name="Email__c" value={item.Email__c}> </lightning-input-field>
<lightning-input-field name="Industry" field-name="Industry" value={item.Industry}> </lightning-input-field>
</lightning-layout-item>
</lightning-layout>
</div>
</template>
<div class="slds-p-around_medium slds-float_right">
<lightning-button class="slds-m-right_small" label="Cancel" onclick={closeModal}></lightning-button>
<lightning-button class="slds-m-top_small" variant="brand" type="submit" name="update" label="Update"></lightning-button>
</div>
</lightning-record-edit-form>
</lightning-modal-body>
</template>
Overriding Default Behaviors
To customize how your form behaves when it loads or when data is submitted, use the onload and onsubmit attributes to specify event handlers. If you handle the submit event yourself, use event.preventDefault()
to stop the form from submitting twice. Errors are handled automatically. To customize how your form behaves when there's an error or when data is submitted successfully, use the onerror and onsuccess attributes to specify event handlers.
import { api } from 'lwc';
import LightningModal from 'lightning/modal';
export default class EditModal extends LightningModal {
@api recordId;
@api label;
@api rowdata;
data = [];
connectedCallback() {
this.data.push(this.rowdata);
}
updateModal(event) {
event.preventDefault();
console.log(event.detail.fields)
let editValues = event.detail.fields;
editValues.Id = this.rowdata["Id"];
const changedData = [{"fields":editValues}]
const update = new CustomEvent('update', {
detail:changedData
})
this.dispatchEvent(update);
this.closeModal();
}
closeModal() {
this.close();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>61.0</apiVersion>
<isExposed>false</isExposed>
</LightningComponentBundle>
public with sharing class TableController {
@AuraEnabled (cacheable=true)
public static List<Account> retrieveAccounts(){
return [SELECT Id, Name, Type, Amount__c, BillingCountry, Email__c, Industry, Website, Phone, Active__c, AccountNumber FROM Account WITH SECURITY_ENFORCED order by CreatedDate DESC];
}
}