1

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

1 Answer 1

0

The problem i see in your component is in below line of code:-

 const result = await updateRecords({data: updatedFields, recordId: this.recordId});

you are passing this.recordId as recordId parameter value which is not the edited record id. Instead this is the current record record id where your component is placed in.

Generally the draft value stores the field that has been edited along with Id of the record. a sample is below:-

[
  {
    FirstName: "Sean",
    Id: "003R0000002J2wHIAS",
  },
  {
    FirstName: "Jack",
    Id: "003R0000002J2wIIAS",
  },
];

you need to modify you apex class with these:-

  1. Instead of having two parameters, just have one. i.e. List<DebitCreditWrapper> recordsToUpdate

  2. you should change

    // Populate fields based on the record
    updatedRecord.put('Id', recordId);
    

to

// Populate fields based on the record
updatedRecord.put('Id', record.recordId);

this ensures that you are getting drafted rows record id for update. Also read this: https://developer.salesforce.com/docs/platform/lwc/guide/data-table-inline-edit.html

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .