0

I am trying to using lightning/uiRecordApi in lightning-datatable to display a list of record and to inline edit some fields and save. In the draftValues I am not getting the Id of the record but I am getting Id as row-0,row-1. Draft values:

[ { "ID_Act_Bill_Qty__c": "7", "Id": "row-0" }, { "ID_Act_Bill_Qty__c": "6", "Id": "row-1" } ] 

I used Id for key-field="Id" not the id. Below is my code.

<lightning-datatable key-field="Id" data={records} columns={columns} onsave={handleSave} draft-values={draftValues} > </lightning-datatable> 
@wire(getProducts, { invoiceId: "$recordId" })productList({error,data}){ if(data){ this.records = data; this.error = undefined; // to show product name let currentData = []; data.forEach((row)=> { let rowData = {}; rowData.ID_Act_Bill_Qty__c = row.ID_Act_Bill_Qty__c; rowData.ID_Quantity_Invoice__c = row.ID_Quantity_Invoice__c; rowData.ID_Net_Value_Bill_Item__c = row.ID_Net_Value_Bill_Item__c; rowData.ID_Remarks__c = row.ID_Remarks__c; if (row.ID_Product__c) { console.log('product Data found'); rowData.ProductCode = row.ID_Product__r.ProductCode; rowData.Description = row.ID_Product__r.Description; } currentData.push(rowData); }); this.records = currentData; console.log('records - '+JSON.stringify(this.records)); }; }; async handleSave(event) { // Convert datatable draft values into record objects console.log('draft values -'+JSON.stringify(event.detail.draftValues)); const records = event.detail.draftValues.slice().map((draftValue) => { const fields = Object.assign({}, draftValue); console.log('fields - '+JSON.stringify(fields)); return { fields }; }); // Clear all datatable draft values this.draftValues = []; try { // Update all records in parallel thanks to the UI API console.log('before update record'); console.log('records update record'+JSON.stringify(records)); const recordUpdatePromises = records.map((record) => updateRecord(record)); console.log('after update record'); await Promise.all(recordUpdatePromises); // Report success with a toast this.dispatchEvent( new ShowToastEvent({ title: "Success", message: "Iventory updated", variant: "success" }) ); // Display fresh data in the datatable await refreshApex(this.records); } catch (error) { this.dispatchEvent( new ShowToastEvent({ title: "Error updating or reloading Inventory", message: error.body, variant: "error" }) ); } } 
2
  • Where the data (this.records) passed to the datatable come from? Could you please edit the question adding that code? Commented Oct 24, 2024 at 8:34
  • @RubenDG I am fetching the records from apex, these contain the fields of parent object as well. Updated the code Commented Oct 24, 2024 at 8:41

1 Answer 1

0

When you handle the records provisioned by the wire adapter, you create a new object for each one (let rowData = {};) and you do not set the Id field, that's why the draftValues fallback on the default one composed by "row-index".
By the way, refreshApex(this.records); won't work because refreshApex needs the whole object provisioned by the wire adapter, not just the data property:

The parameter you refresh with refreshApex() must be an object that was previously emitted by an Apex @wire.

To fix this issue change that wired function to:

wiredRecords; @wire(getProducts, { invoiceId: "$recordId" }) productList(result){ this.wiredRecords = result; // wiredRecords will be used by refreshApex const { data, error } = result; if (data) { this.error = undefined; this.records = data.map((row) => { const rowData = {}; rowData.Id = row.Id; // Store the original Id rowData.ID_Act_Bill_Qty__c = row.ID_Act_Bill_Qty__c; rowData.ID_Quantity_Invoice__c = row.ID_Quantity_Invoice__c; rowData.ID_Net_Value_Bill_Item__c = row.ID_Net_Value_Bill_Item__c; rowData.ID_Remarks__c = row.ID_Remarks__c; if (row.ID_Product__c) { console.log('product Data found'); rowData.ProductCode = row.ID_Product__r.ProductCode; rowData.Description = row.ID_Product__r.Description; } return rowData; }); console.log('records - '+JSON.stringify(this.records)); }; } 

Array.map() creates a new array with each element being the result of the callback function.

Then change

await refreshApex(this.records); 

to

await refreshApex(this.wiredRecords); 
5
  • Adding rowData.Id = row.Id; solved the ID issue but replacing productList({error,data}){ if(data){ as productList(result){ this.wiredRecords = result; // wiredRecords will be used by refreshApex if (data) { is giving an error for variable Data as undefined Commented Oct 24, 2024 at 9:36
  • @Raham My bad, I forgot a line. I edited the answer Commented Oct 24, 2024 at 9:41
  • Thanks @RubenDG !! The refresh of inline edited cells are some times not proper if I refresh multiple cells in one go and click save. Is there a way to refresh the whole component? Commented Oct 24, 2024 at 9:54
  • @Raham What do you mean by "not proper", could you please explain that in more detail? Commented Oct 24, 2024 at 10:12
  • @ RubenDG Suppose if I edit 3 cells and click save, some times the values in the cells are not getting refreshed. May be the cell is getting refreshed first and then value is getting saved in data base! Can we add some delay to refresh Commented Oct 24, 2024 at 10:43

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.