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
Lokesh Krishna SagiLokesh Krishna Sagi 

inline edit of Lightning dataTable

Hi,

I am trying to work out features of lightning dataTable and I am currently stuck at inline edit feature. I have created 2 components (both are independent) for 2 inline edit examples. 1st one is working as expected but the 2nd component is not working. 

Whenever I change some value in any row, it is suppossed to call Server controller. But my code never reaching server controller.. I am posting the entire code here. Please Help!!
Component
-------------------

<aura:component controller = "AdvancedORCASearchClass" 
                implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" >
    
    <aura:attribute name="searchData" type="Object" />
    <aura:attribute name="data" type="List" default="[]" />
    <aura:attribute name="columns" type="List" />
    <aura:attribute name="mySelectedRows" type="Object[]" />
    <aura:attribute name="selectedRowsCount" type="Integer" default="0" />
    <aura:attribute name="maxRowSelection" type="Integer" default="5"/>
    <aura:attribute name="isButtonEnabled" type="boolean" default="false" />
    
    <aura:attribute name="selectedIds" type="List" />
    
    <aura:attribute name="allData" type="List"/>
    <aura:attribute name="rowsToDisplay" type="Integer" default="7" />
    <aura:attribute name="totalPages" type="Integer" />
    <aura:attribute name="currentPageNumber" type="Integer" default="1"/>
    
    <aura:attribute name="enableInfiniteLoading" type="boolean" default="true" />
    <aura:attribute name="totalRows" type="Integer" />
    <aura:attribute name="offsetNumber" type="Integer" default="0" />
    <aura:attribute name="initialRows" type="Integer" default="7" />
    <aura:attribute name="isLoading" type="boolean" default="false" />
    <aura:attribute name="loadMoreStatus" type="String" default="" />
    
    
    <aura:attribute name="selection" type="List" access="PRIVATE"/>
    
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    <!-- <aura:handler event="c:AdvORCASendRecordId" action="{!c.refreshComponent}" />  -->
    <!--    <aura:handler event="force:refreshView" action="{!c.doInit}" /> -->
    
    <aura:method name="search" action="{!c.getSearchResult}">
        <aura:attribute name="fromDate" type="Date"/>
        <aura:attribute name="toDate" type="Date" />
        <aura:attribute name="selectedStatuses" type="String[]" />
        
    </aura:method>
    
    <lightning:navigation aura:id="navService" />
    
    <aura:if isTrue="{!v.isButtonEnabled}">
        <lightning:layout horizontalAlign="center">
            <lightning:layoutItem  padding="around-large">
                
                <lightning:button iconName="action:download" iconPosition="right" label="Download Selected" onclick="{!c.onDownload}" 
                                  variant="brand" />
                
            </lightning:layoutItem>
        </lightning:layout>
    </aura:if>
    
    <lightning:layout horizontalAlign="center" multipleRows="true">
        
        <lightning:layoutItem size="12">
            <div style="height: 300px">
                <lightning:dataTable  
                                     aura:id="dataTable"
                                     columns="{!v.columns}"
                                     data="{!v.data}"
                                     keyField="id"
                                     enableInfiniteLoading="{!v.enableInfiniteLoading}"
                                     onloadmore="{!c.loadMoreData}"
                                     isLoading="{!v.isLoading}"
                                     hideCheckboxColumns="false"
                                     onrowaction="{!c.handleRowAction}"
                                     maxRowSelection="{! v.maxRowSelection }"
                                     onrowselection="{! c.updateSelectedText }" 
                                     onsave="{! c.onSave}"
                                     />
            </div>
        </lightning:layoutItem>
        
        <aura:if isTrue="{!v.isButtonEnabled}">
            <lightning:layoutItem size="12" class="centerAlign">
                {!v.loadMoreStatus}
            </lightning:layoutItem>
            

    </lightning:layout>
    
</aura:component>
-----------------------------------------------------------------------------------------

Client Controller
---------------------------

({
    getSearchResult : function(component, event, helper) {
        component.set('v.data', []); 
        component.set('v.offsetNumber', 0);
        component.set('v.enableInfiniteLoading', true);
        //$A.get('e.force:refreshView').fire();
        var parameters = event.getParam('arguments');
        //alert('Data is set to [] here');
        if(parameters) {
            component.set('v.searchData', parameters); 
            
            //alert('Params are set here. To Helpers');
            
            helper.getTotalRows(component, event, helper);
            
            //alert('Helper1 is done');
            
            helper.getSearchResults(component, event, helper, component.get('v.offsetNumber'));
            //alert('Helper2 is done. Data size=='+component.get('v.data').length);
        }
    },
    
    /* refreshComponent : function(component, event, helper) {
        $A.get('e.force:refreshView').fire();
    }, */
    
    doInit : function(component, event, helper) {
        //component.set('v.data', []);
        //alert('length===='+component.get('v.data').length);
        
        var actions = [{label:"Change Status", name:"update_Status"},
                       {label:"Delete", name:"delete"}];        
        component.set('v.columns', [
            {label:"Incident Number", fieldName:"Name", type:"text"},
            {label:"View", type:"button", typeAttributes:{label:"View", name:"view_details", title:"Click here to View Details"}},
            {label:"Title", fieldName:"Title__c", type:"text", editable:true},
            {label:"Date", fieldName:"Incident_Date__c", type:"Date"},
            {label:"Risk Category", fieldName:"Risk_Category__c", type:"text"},
            {label:"Status", fieldName:"Status__c", type:"text"},
            {label:"Ops Risk Region", fieldName:"Ops_Risk_Region__c", type:"text"},
            {label:"Recorder", fieldName:"linkNameRec", type:"url", typeAttributes:{label:{fieldName:"Recorder__c"}, target:"_blank"}},
            {label:"Reviewer", fieldName:"linkNameRev", type:"url", typeAttributes:{label:{fieldName:"Reviewer__c"}, target:"_blank"}},
            {label:"Approver", fieldName:"linkNameApp", type:"url", typeAttributes:{label:{fieldName:"Approver__c"}, target:"_blank"}},
            {type:'action', typeAttributes:{rowActions:actions}}
        ]);
    },
    
    handleRowAction : function(component, event, helper) {
        var action = event.getParam('action');
        var row = event.getParam('row');
        switch (action.name) {
            case 'view_details':
                var navEvent = $A.get("e.force:navigateToSObject");
                if(navEvent) {
                    navEvent.setParams({
                        "recordId" : row.Id,
                        "slideDevName" : "detail"
                    });
                    window.open('/'+event.getParam('row').Id);
                }
                break;
                
            case 'delete':
                alert('Please dont delete me....');
                break;
                
            case 'update_Status':
                /*var appEvent = $A.get('e.c:AdvORCASendRecordId');
                appEvent.setParams({
                    "recordId":row.Id
                });
                alert('Before Firing');
                appEvent.fire();
                alert('After Firing'); */
                var navService = component.find('navService');
                var pageReference = {
                    "type":"standard__component", 
                    "attributes":{"componentName":"c__AdvancedORCAChangeStatus"},
                    "state":{recordId:row.Id}};
                navService.navigate(pageReference);
                //alert('KeyField:::'+row.keyField);
                
                break;
        }
    },
    
    onDownload : function(component, event, helper) {
        //alert('Selected Rows::'+component.get('v.mySelectedRows'));
        var stockData = component.get('v.mySelectedRows');
        
        if(stockData.length == 0) {
            alert('Please select at least one row to export results');
        }
        else {
            var csv = helper.convertArrayOfObjectsToCSV(component,stockData);
            
            if (csv == null){
                return;
            } 
            
            var hiddenElement = document.createElement('a');
            hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
            hiddenElement.target = '_self'; // 
            hiddenElement.download = 'ExportData.csv';  // CSV file Name* you can change it.[only name not .csv] 
            document.body.appendChild(hiddenElement); // Required for FireFox browser
            hiddenElement.click(); // using click() js function to download csv file
        }
        
    },
    
    updateSelectedText : function(component, event, helper) {
        //component.set('v.selectedIds', component.find('dataTable').get('v.keyField').Id);
        // alert('Selected IDs::'+component.get('v.selectedIds'));
        var selectedRows = event.getParam('selectedRows');
        component.set('v.mySelectedRows', selectedRows);
        
    },
   
    
    loadMoreData : function(component, event, helper) {
        //alert('Success untill here');
        //event.getSource().set("v.isLoading", true);
        component.set('v.isLoading', true);
        component.set('v.loadMoreStatus', 'Loading');
        component.set('v.offsetNumber', component.get('v.data').length);
        //alert('offset::'+component.get('v.offsetNumber'));
        helper.getSearchResults(component, event, helper, component.get('v.offsetNumber'));
    },
    
    onSave : function(component, event, helper) {
       // var editedRecords = component.find('dataTable').get('v.draftValues');
      //  alert('Number of records edited:'+editedRecords.length);
        helper.onEdit(component, event, helper);
    }
})
----------------------------------------------------------------------------------------------

Helper
--------------------
({
    getSearchResults : function(component, event, helper, offNumber) {
        //alert('Inside Helper');
        //alert('Offset Number::'+offNumber);
        var action1 = component.get('c.searchWithInputs');
        action1.setParams({
            fromDate:component.get('v.searchData').fromDate,
            toDate:component.get('v.searchData').toDate,
            statuses:component.get('v.searchData').selectedStatuses,
            rowsToDisplay:component.get('v.rowsToDisplay'),
            offsetNumber:offNumber
        });        
        action1.setCallback(this, function(response) {
            var state = response.getState();
            
            if(state==='SUCCESS') {
                //alert('Inside For');
                for(var i=0; i<response.getReturnValue().length; i++) {
                    // alert('Inside For');
                    var row = response.getReturnValue()[i];
                    
                    row.linkNameRec = "/"+row.Recorder__c;
                    row.Recorder__c = row.Recorder__r.Name;
                    
                    row.linkNameRev = "/"+row.Reviewer__c;
                    row.Reviewer__c = row.Reviewer__r.Name;
                    
                    row.linkNameApp = "/"+row.Approver__c;
                    row.Approver__c = row.Approver__r.Name;   
                }
                
                if(component.get('v.data').length >= component.get('v.totalRows')) {
                    component.set('v.enableInfiniteLoading', false);
                    component.set('v.loadMoreStatus', 'No more records to load.');
                }
                else {
                    var currentData = component.get('v.data');
                    var newData = currentData.concat(response.getReturnValue());
                    component.set('v.data', newData);
                    component.set('v.loadMoreStatus', '');   
                    //alert('Alert for length++++'+component.get('v.data').length);
                }
                component.set('v.isLoading', false);
                //event.getSource().set("v.isLoading", false);
                
                
                //component.set('v.totalPages', Math.ceil(response.getReturnValue().length/component.get('v.rowsToDisplay')));
                // component.set('v.data', response.getReturnValue());
                // component.set('v.currentPageNumber',1);
                
                if(component.get('v.isButtonEnabled') == false) {
                    component.set('v.isButtonEnabled', true);
                }
                
                
                //  helper.setData(component, event, helper);
            }
        });
        $A.enqueueAction(action1);
    },
    
    getTotalRows : function(component, event, helper) {
        var action2 = component.get('c.getCountIncidents');
        action2.setParams({
            fromDate:component.get('v.searchData').fromDate,
            toDate:component.get('v.searchData').toDate,
            statuses:component.get('v.searchData').selectedStatuses
            
        });    
        action2.setCallback(this, function(response) {
            var state = response.getState();
            
            if(state==='SUCCESS') {
                component.set('v.totalRows', response.getReturnValue().length);
            }
        });
        $A.enqueueAction(action2);
    },
    
    
    /* 
    setData : function(component, event, helper) {
        var data = [];
        var pageNumber = component.get('v.currentPageNumber');
        var totalPages = component.get('v.totalPages');
        var rowsToDisplay = component.get('v.rowsToDisplay');
        var allData = component.get('v.allData');
        
        var x = (pageNumber-1)*rowsToDisplay;
        
        for(;x<=(pageNumber)*(rowsToDisplay);x++) {
            if(allData[x]) {
                data.push(allData[x]);
            }
        }
        component.set('v.data', data);
    },
    */
    convertArrayOfObjectsToCSV : function(component, objectRecords) {
        var csvStringResult, counter, keys, columnDivider, lineDivider;
        if(objectRecords == null && !objectRecords.length) {
            return null;
        }
        columnDivider = ',';
        lineDivider = '\n';
        keys = ['Name', 'Title__c', 'Incident_Date__c', 'Risk_Category__c', 'Status__c', 'Ops_Risk_Region__c',
                'Recorder__c', 'Reviewer__c', 'Approver__c'];
        csvStringResult = '';
        csvStringResult += keys.join(columnDivider);
        csvStringResult += lineDivider;
        
        for(var i=0; i<objectRecords.length; i++) {
            counter = 0;
            for(var sTempkey in keys) {
                var skey = keys[sTempkey] ;  
                
                
                if(counter > 0){ 
                    csvStringResult += columnDivider; 
                }   
                
                csvStringResult += '"'+ objectRecords[i][skey]+'"'; 
                
                counter++;
                
            } 
            csvStringResult += lineDivider;
        }
        
        //alert('Returning thing:::'+csvStringResult);
        return csvStringResult; 
    },
    
    onEdit : function(component, event, helper) {
        var editedRecords = event.getParam('draftValues');
        var totalRecordEdited = editedRecords.length;
        
        var action = component.get("c.updateRecords");
        
        action.setParams({
            "editedAccounts" : editedRecords
        });
        
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === 'SUCCESS') {
                
                if(response.getReturnValue() === true) {
                    helper.showToast({
                        "title" : 'Record Update',
                        "type" : "success",
                        "message" : totalRecordEdited + " Records updated"
                    });
                    helper.reloadDataTable();
                }
                else {
                    helper.showToast({
                        "title": "Error!!",
                        "type": "error",
                        "message": "Error in update"
                    });
                }
            }
        });
        
        $A.enqueueAction(action);
    },
    
    showToast : function(params){
        var toastEvent = $A.get("e.force:showToast");
        if(toastEvent){
            toastEvent.setParams(params);
            toastEvent.fire();
        } else{
            alert(params.message);
        }
    },
    
    reloadDataTable : function(){
    var refreshEvent = $A.get("e.force:refreshView");
        if(refreshEvent){
            refreshEvent.fire();
        }
    },
    
})
---------------------------------------------------------------------------------------------------

Server Controller -- Apex Class
-----------------------------------------
public class AdvancedORCASearchClass {
    @AuraEnabled
    public static boolean updateRecords(List<Incident__c> editedAccounts) {
        system.debug(editedAccounts);
        try{
            update editedAccounts;
            return true;
        }
        catch(Exception e) {
            return false;
        }
    }
}

 
Best Answer chosen by Lokesh Krishna Sagi
Lokesh Krishna SagiLokesh Krishna Sagi
The reason for this error lies in mentioning 'KeyField' of dataTable. I have mentioned it as 'id' but it should be 'Id'