function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Gopal ChatGopal Chat 

Component not updating the record on save button

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" controller="AccountSearchController">
    <aura:attribute name="searchKeyword" type="String" default=""/>
    <aura:attribute name="lstOfAccount" type="Account[]"/>
    <aura:attribute name="listcontact" type="Contact[]"/>
    <aura:attribute name="columns" type="List"/>
    <aura:attribute name="isBlank" type="boolean" default="false"/>
    <aura:attribute name="recordId" type="String"/>
    <aura:attribute name="updatedRecord" type="Object[]" />
    
    <div class="slds-m-around_medium" style="background:#fff">
        <lightning:layout>
            <lightning:layoutItem padding="around-small">
                 <lightning:spinner variant="brand" size="medium" aura:id="Id_spinner" class="slds-hide" />
                <h1 class="slds-page-header__title slds-truncate slds-align-middle" 
                    title="Enter Account Name">Enter Account Name</h1>
                <lightning:input value="{!v.searchKeyword}" required="true"  aura:id="searchKeyword"/>
            </lightning:layoutItem>
        </lightning:layout>
        
        <lightning:layout>
            <lightning:layoutItem size="2" padding="around-small">
                <lightning:button onclick="{!c.Search}" variant="brand" label="Search" iconName="utility:search"/>
            </lightning:layoutItem>
        </lightning:layout>
        <aura:if  isTrue="{!and(v.isBlank, v.lstOfAccount!=NULL)}">
                <lightning:card title="Account Records" variant="brand">
                    <lightning:datatable  columns="{! v.columns }" data="{!v.lstOfAccount}"  
                                          hideCheckboxColumn="true" keyField="Id" onsave ="{!c.Save}"/>
                </lightning:card>
         </aura:if>
    </div>
</aura:component>
({
    Search : function(component, event, helper) {
        component.set('v.columns', [
            {label: 'Name', fieldName: 'Name', editable:'true', type: 'text'},
            {label: 'Phone', fieldName: 'Phone', editable:'true', type: 'Phone'},
            {label: 'Industry', fieldName: 'Industry', editable:'true', type: 'text'}]); 
        var action = component.get("c.fetchAccount");
        action.setParams({
            "searchKeyWord" : component.get("v.searchKeyword")
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.lstOfAccount", response.getReturnValue());
                component.set("v.isBlank",true);
                if(response.getReturnValue()==null){
                    var toast = $A.get("e.force:showToast");
                    toast.setParams({
                        "type":"Error",
                        "title":"Error",
                        "message":"No Account Found",
                        "duration":1000
                    });
                    toast.fire();
                }
            }
        });
        $A.enqueueAction(action);
    },
    Save : function (component,event,helper){
      var action=component.get("c.saveAccount");
        action.setParams({
           "AccListStr":JSON.stringify(component.get("v.lstOfAccount"))
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                component.set("v.lstOfAccount", response.getReturnValue());
                alert(response.getReturnValue());
                var toast = $A.get("e.force:showToast");
                toast.setParams({
                    "type":"Success",
                    "title":"Success",
                    "message":"Account Saved Successfully",
                    "duration":1000
                });
            toast.fire();
            }
        });
        $A.enqueueAction(action);
    }
})
public class AccountSearchController{
    
    @AuraEnabled
    public static List <Account> fetchAccount(String searchKeyWord) {
        String searchKey = searchKeyWord +'%';
        List <Account> lstOfAccount = [SELECT Id, Name,Phone,Industry FROM Account
                                       WHERE Name LIKE:searchKey];
        
        system.debug('==>'+lstOfAccount);
        if(lstOfAccount.size() > 0)
            return lstOfAccount;
        else return null;
    }
    @auraEnabled
    public static List<Account>  saveAccount(String AccListStr){
        List<Account> accList = (List<Account>)json.deserialize(AccListStr, List<Account>.class);
        update accList;
        system.debug('===>accList'+accList);
        return accList;
    }
}
Khan AnasKhan Anas (Salesforce Developers) 
Hi Gopal,

I trust you are doing very well.

Below is the sample code for update records in DataTable, which I have tested in my org and it is working fine. Kindly modify the code as per your requirement.

sObject: Registration_Form__c​
Fields: Name, Parents_Name__c, Class_Name__c​


Component:
<aura:component controller="UpdateDataTable_TaskSvrController"
                implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
	
    <aura:attribute name="PageHeading" type="String" default="Update Using Data Table"/>
    <aura:attribute name="mydata" type="Registration_Form__c"/>
    <aura:attribute name="mycolumns" type="List"/>
    
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <aura:handler event="force:refreshView" action="{!c.doInit}" />
    
    <div class="slds-m-top--xx-large">
    	<div class="slds-page-header">
    		<div class="slds-align--absolute-center">
        		<div class="slds-text-heading--large">       
    				{!v.PageHeading}
                </div>
        	</div>
    	</div>
    </div>
    <br/> <br/>
    
    <div id="dt">
        <lightning:datatable aura:id="iliDataTable"
                             data="{! v.mydata }" maxRowSelection="1" 
                             columns="{! v.mycolumns }" 
                             keyField="Id" 
                             hideCheckboxColumn="true" 
                             onsave="{!c.saveTable}" />
    </div>
</aura:component>

Controller:
({
    doInit : function(component, event, helper) {
        component.set('v.mycolumns', [
            {label: 'Student Name', fieldName: 'Name', type: 'text', editable: true, initialWidth: 750},
            {label: 'Parents Name', fieldName: 'Parents_Name__c', type: 'text', editable: true},
            {label: 'Class Name', fieldName: 'Class_Name__c', type: 'text', editable: true}
        ]);
        
        var action = component.get("c.details");
        action.setCallback(this, function(response) {
            var state = response.getState();
            
            if (state === "SUCCESS") {
                var res = response.getReturnValue();
                component.set("v.mydata", res);
            }
            else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " + 
                                 errors[0].message);
                    }
                } 
                else {
                    console.log(response.getReturnValue());
                }
            }
        });
        $A.enqueueAction(action);
    },
    
    saveTable : function(component, event, helper){     
        //var data = component.get("v.mydata");
        var draftValues = event.getParam('draftValues');
        var action = component.get("c.updateDetails");
        action.setParams({lstForm  : draftValues});
        action.setCallback(this, function(response) {
            var state = response.getState();
            
            if (state === "SUCCESS") {
                var res = response.getReturnValue();
                $A.get('e.force:refreshView').fire();
                alert('Updated Successfully...');
            }
            else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " + 
                                    errors[0].message);
                    }
                } 
                else {
                    console.log(response.getReturnValue());
                }
            }
        });
        $A.enqueueAction(action);
    }
})

Apex:
public class UpdateDataTable_TaskSvrController {
    
    @AuraEnabled
    public static List<Registration_Form__c> details(){
        List<Registration_Form__c> lst = [SELECT Name, Parents_Name__c, Class_Name__c FROM Registration_Form__c LIMIT 10];
        return lst;
    }

    @AuraEnabled
    public static List<Registration_Form__c> updateDetails(List<Registration_Form__c> lstForm) {
        update lstForm;
        return lstForm;
    }
}

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in future.

Thanks and Regards,
Khan Anas
Gopal ChatGopal Chat
Can you please check,what is the problem with my code
Khan AnasKhan Anas (Salesforce Developers) 
Hi Gopal,

According to the documentation (https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/documentation) for lightning:datatable, the changed values are retrieved from event.getParam('draftValues')

Retrieve the new value using event.getParam('draftValues').
The 
draftValues data structure is an array of objects. Each object describes the changed values by specifying the keyField to identify the row containing the changed values, the data column name, and the changed value for that column. The data structure is useful to make a server side call that persists the changes in the datatable.

So you will need to change your JS code:
Save : function (component,event,helper){
        var action=component.get("c.saveAccount");
        var draftValues = event.getParam('draftValues');
        action.setParams({
            "accList":draftValues
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                component.set("v.lstOfAccount", response.getReturnValue());
                alert(JSON.stringify(response.getReturnValue()));
                var toast = $A.get("e.force:showToast");
                toast.setParams({
                    "type":"Success",
                    "title":"Success",
                    "message":"Account Saved Successfully",
                    "duration":1000
                });
                toast.fire();
            }
        });
        $A.enqueueAction(action);
    }

And in apex change update method i.e; saveAccount method:
@auraEnabled
    public static List<Account> saveAccount(List<Account> accList){
        update accList;
        system.debug('===>accList'+accList);
        return accList;
    }


I hope it helps you.

Kindly mark this as solved if it's resolved so that it gets removed from the unanswered queue which results in helping others who are encountering a similar issue.

Regards,
Khan Anas