I've been trying to find an example to go off of, but not finding anything relevant. I've created a custom data-table in an LWC which pulls data from two separate objects and compiles them into a data-table. I'm trying to enable inline editing feature but I can't get it to pull the right information.
It seems to pull the row number from draftValues but that's all it appears to pass to the apex. I think it may have to do with my wrapper class I'm using to compile the information. Any ideas are welcome. Relevant code to follow:
JS:
import { LightningElement, wire, api } from 'lwc';
import getData from '@salesforce/apex/DebitCreditController.getData';
import updateRecords from '@salesforce/apex/DebitCreditController.updateRecords';
import { notifyRecordUpdateAvailable } from "lightning/uiRecordApi";
import {ShowToastEvent} from 'lightning/platformShowToastEvent';
import { refreshApex } from '@salesforce/apex';
const COLUMNS = [
{ label: 'Date',
fieldName: 'Date_c',
type: 'date',
sortable: true,
resizeable: true,
initialWidth: 150,
editable: true,
cellAttributes: { class: { fieldName: 'reconciledClass' } }
},
{ label: 'Payee',
fieldName: 'Payee_c',
type: 'text',
sortable: true,
resizeable: true,
editable: true,
cellAttributes: { class: { fieldName: 'reconciledClass' } }
},
{ label: 'Memo',
fieldName: 'Memo_c',
type: 'text',
sortable: true,
resizeable: true,
editable: true,
cellAttributes: { class: { fieldName: 'reconciledClass' } }
},
{ label: 'Category',
fieldName: 'Category_c',
type: 'text',
sortable: true,
resizeable: true,
editable: true,
cellAttributes: { class: { fieldName: 'reconciledClass' } }
},
{ label: 'Sub Category',
fieldName: 'Sub_Category_c',
type: 'text',
sortable: true,
resizeable: true,
editable: true,
cellAttributes: { class: { fieldName: 'reconciledClass' } }
},
{ label: 'Amount',
fieldName: 'Amount_c',
type: 'currency',
typeAttributes: { currencyCode: 'USD' },
sortable: true,
resizeable: true,
editable: true,
cellAttributes: { class: { fieldName: 'reconciledClass' } }
},
{ label: 'Reconciled',
fieldName: 'Reconciled_c',
type: 'text',
sortable: true,
resizeable: true,
editable: true,
cellAttributes: { class: { fieldName: 'reconciledClass' } }
}
];
export default class DebitCreditDataTable extends LightningElement
{
@api recordId;
rawData = [];
data = [];
draftValues = [];
columns = COLUMNS;
sortBy;
sortDirection;
@wire(getData)
wiredData({ error, data }) {
if (data) {
this.rawData = data.map(item=>{
let reconciledClass = this.getRowColorClass(item.Reconciled_c);
return {...item,
"reconciledClass":reconciledClass
}
});
console.log(this.rawData);
} else if (error) {
console.error(error)
}
}
async handleSave(event)
{
const updatedFields = event.detail.draftValues;
// Prepare the record IDs for notifyRecordUpdateAvailable()
const notifyChangeIds = updatedFields.map(row => { return { "recordId": row.recordId } });
console.log('notifyChangeIds => ', JSON.parse(JSON.stringify(notifyChangeIds)));
try
{
// Pass edited fields to the updateContacts Apex controller
const result = await updateRecords({data: updatedFields, recordId: this.recordId});
console.log(JSON.stringify("Apex update result: "+ result));
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Changes Made!',
variant: 'success'
})
);
// Refresh LDS cache and wires
notifyRecordUpdateAvailable(notifyChangeIds);
// Display fresh data in the datatable
await refreshApex(this.rawData);
// Clear all draft values in the datatable
this.draftValues = [];
} catch(error) {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error updating or refreshing records',
message: error.message,
variant: 'error'
})
);
};
}
}
Apex:
public with sharing class DebitCreditController
{
@AuraEnabled(cacheable=true)
public static List<DebitCreditWrapper> getData()
{
List<Debit__c> debitRecords = [SELECT Id,
Date__c,
Payee__c,
Memo__c,
Category__r.Name,
Sub_Category__r.Name,
Amount__c,
Reconciled__c
FROM Debit__c
ORDER BY Date__c DESC];
List<Credit__c> creditRecords = [SELECT Id,
Date__c,
Payee__c,
Memo__c,
Category__r.Name,
Sub_Category__r.Name,
Amount__c,
Reconciled__c
FROM Credit__c
ORDER BY Date__c DESC];
List<DebitCreditWrapper> result = new List<DebitCreditWrapper>();
for (Debit__c debitRecord : debitRecords) {
result.add(new DebitCreditWrapper(debitRecord.Id, debitRecord.Date__c, debitRecord.Payee__c, debitRecord.Memo__c, debitRecord.Category__r.Name, debitRecord.Sub_Category__r.Name, debitRecord.Amount__c, debitRecord.Reconciled__c));
}
for (Credit__c creditRecord : creditRecords) {
result.add(new DebitCreditWrapper(creditRecord.Id, creditRecord.Date__c, creditRecord.Payee__c, creditRecord.Memo__c, creditRecord.Category__r.Name, creditRecord.Sub_Category__r.Name, creditRecord.Amount__c, creditRecord.Reconciled__c));
}
result.sort();
System.debug('Results: ' + result);
return result;
}
@AuraEnabled
public static void updateRecords(List<DebitCreditWrapper> recordsToUpdate, Id recordId) {
List<SObject> recordsToUpdateSObjects = new List<SObject>();
System.debug('recordsToUpdate: ' + recordsToUpdate);
try{
for (DebitCreditWrapper record : recordsToUpdate) {
//Id recordId = recordId;
SObjectType sObjectType = recordId.getSObjectType();
// Use the SObjectType to create a dynamic instance of the object
SObject updatedRecord = sObjectType.newSObject(recordId);
// Populate fields based on the record
updatedRecord.put('Id', recordId);
updatedRecord.put('Date_c', record.Date_c);
updatedRecord.put('Payee_c', record.Payee_c);
updatedRecord.put('Memo_c', record.Memo_c);
updatedRecord.put('Category_c', record.Category_c);
updatedRecord.put('Sub_Category_c', record.Sub_Category_c);
updatedRecord.put('Amount_c', record.Amount_c);
updatedRecord.put('Reconciled_c', record.Reconciled_c);
recordsToUpdateSObjects.add(updatedRecord);
}
update recordsToUpdateSObjects;
}catch(Exception e)
{
System.debug('EXCEPTION CAUGHT! ==> ' + e.getMessage());
throw new AuraHandledException(e.getMessage());
}
}
public class DebitCreditWrapper implements Comparable
{
@AuraEnabled public Id recordId;
@AuraEnabled public Date Date_c;
@AuraEnabled public String Payee_c;
@AuraEnabled public String Memo_c;
@AuraEnabled public String Category_c;
@AuraEnabled public String Sub_Category_c;
@AuraEnabled public Decimal Amount_c;
@AuraEnabled public String Reconciled_c;
// Default constructor
/* public DebitCreditWrapper()
{
// Initialize your variables if needed
this.recordId = null;
this.Date_c = null;
this.Payee_c = null;
this.Memo_c = null;
this.Category_c = null;
this.Sub_Category_c = null;
this.Amount_c = null;
this.Reconciled_c = null;
} */
public DebitCreditWrapper(Id recordId, Date Date_c, String Payee_c, String Memo_c, String Category_c, String Sub_Category_c, Decimal Amount_c, String Reconciled_c)
{
this.recordId = recordId;
this.Date_c = Date_c;
this.Payee_c = Payee_c;
this.Memo_c = Memo_c;
this.Category_c = Category_c;
this.Sub_Category_c = Sub_Category_c;
this.Amount_c = Amount_c;
this.Reconciled_c = Reconciled_c;
}
public Integer compareTo(Object compareTo)
{
DebitCreditWrapper compareToDate = (DebitCreditWrapper) compareTo;
if (Date_c == compareToDate.Date_c) return 0;
if (Date_c < compareToDate.Date_c) return 1;
return -1;
}
}
}
Regards, JH