Skip to content

Instantly share code, notes, and snippets.

@tushar30
Last active March 18, 2019 16:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tushar30/302a4a6c804343f19dcd7ffa99ccff6f to your computer and use it in GitHub Desktop.
Save tushar30/302a4a6c804343f19dcd7ffa99ccff6f to your computer and use it in GitHub Desktop.
<aura:application extends="force:slds">
<aura:attribute name="userData" type="List" default="[]"/>
<aura:attribute name="tableHeight" type="Integer" default="450"/>
<aura:attribute name="sortedDirection" type="String" default="DESC"/>
<aura:attribute name="inlineEdit" type="boolean" default="true"/>
<aura:attribute name="enableColAction" type="boolean" default="true"/>
<c:DataTableLazyLoading selectedData="{!v.userData}" tableHeight="{!v.tableHeight}"
sortedDirection="{!v.sortedDirection}" inlineEdit="{!v.inlineEdit}"
enableColAction ="{!v.enableColAction}"/>
Selected Rows: <br/> <br/>
<aura:iteration items="{!v.userData}" var="item">
{!item.Id}<br/>
</aura:iteration>
</aura:application>
public class DataTableController {
@AuraEnabled
public static DataTableWrapper initRecords(String ObjectName, String fieldNamesStr, String Orderby, String OrderDir, boolean inlineEdit, boolean enableColAction) {
DataTableWrapper dtw = new DataTableWrapper();
List<LabelDescriptionWrapper> labelList = new List<LabelDescriptionWrapper>();
List<String> fieldSet = new List<String>();
Set<String> fieldNameSet = new Set<String>(fieldNamesStr.split(','));
if(Schema.getGlobalDescribe().containsKey(ObjectName) ) {
sObject sObj = Schema.getGlobalDescribe().get(ObjectName).newSObject() ;
//get all the labels for Opportunity fields and put them in a map, keyed to the field api name
Map<String, Schema.SObjectField> fieldMap = Schema.getGlobalDescribe().get(ObjectName).getDescribe().fields.getMap();
Map<Schema.SObjectField,String> fieldToAPIName = new Map<Schema.SObjectField,String>();
Map<String, String> apiNameToLabel = new Map<String, String>();
for(String fieldName : fieldNameSet){
if(fieldMap.containsKey(fieldName)) {
fieldSet.add(fieldName);
labelList.add(new LabelDescriptionWrapper(fieldMap.get(fieldName).getDescribe().getLabel(), fieldName, fieldMap.get(fieldName).getDescribe().getType().name().toLowerCase(), true,inlineEdit, null ));
}
}
//add action
if(enableColAction) {
List<Actions> actionList = new List<Actions>();
actionList.add(new Actions('Edit','Edit'));
actionList.add(new Actions('View','View'));
actionList.add(new Actions('Delete','Delete'));
TypeAttributes tAttribute = new TypeAttributes(actionList);
labelList.add(new LabelDescriptionWrapper('Actions', 'Actions', 'action', false, false, tAttribute ));
}
//call method to query
List<sObject> sObjectRecords = getsObjectRecords(ObjectName, fieldSet, 50, '', Orderby, OrderDir);
dtw.ldwList = labelList;
dtw.sobList = sObjectRecords;
dtw.fieldsList = fieldSet;
dtw.totalCount = Database.countQuery('SELECT count() FROM '+ObjectName);
}
return dtw;
}
@AuraEnabled
public static List<sObject> getsObjectRecords(String ObjectName, List<String> fieldNameSet, Integer LimitSize, String recId, String Orderby, String OrderDir) {
OrderDir = String.isBlank(OrderDir) ? 'asc' : OrderDir;
String query = 'SELECT '+String.join(fieldNameSet, ',')+' FROM '+ObjectName;
if(String.isNotBlank(recId)) {
recId = String.valueOf(recId);
query += ' WHERE ID >: recId ';
}
query += ' ORDER BY '+Orderby+' '+OrderDir+' NULLS LAST';
if(LimitSize != null && Integer.valueOf(LimitSize) > 0) {
LimitSize = Integer.valueOf(LimitSize);
query += ' Limit '+LimitSize;
}
return Database.query(query);
}
@AuraEnabled
public static sObject deleteSObject(sObject sob) {
delete sob;
return sob;
}
@AuraEnabled
public static void updateRecords(List<sObject> sobList, String updateObjStr, String objectName) {
//
System.debug(updateObjStr);
System.debug(sobList);
schema.SObjectType sobjType = Schema.getGlobalDescribe().get(ObjectName);
Map<String, Schema.sObjectField> sObjectFields = sobjType.getDescribe().fields.getMap();
List<sObject> updateList = new List<sObject>();
List<Object> obList = (List<object>) json.deserializeUntyped(updateObjStr);
for(object ob : obList) {
Map<String, object> obmap = (Map<String, object>)ob;
String rowKey = (String)obmap.get('id');
Integer rowKeyInt = Integer.ValueOf(rowKey.removeStart('row-'));
sobject sObj = sobList[rowKeyInt];
for(string fieldName : obmap.keySet()) {
if(fieldName != 'id') {
Object value = obmap.get(fieldName);
Schema.DisplayType valueType = sObjectFields.get(fieldName).getDescribe().getType();
if (value instanceof String && valueType != Schema.DisplayType.String)
{
String svalue = (String)value;
if (valueType == Schema.DisplayType.Date)
sObj.put(fieldName, Date.valueOf(svalue));
else if(valueType == Schema.DisplayType.DateTime) {
try{
System.debug( (DateTime)value);
}catch(exception ex) {
system.debug(ex.getmessage());
}
String d1 = svalue;
list<String> d2 = d1.split('-');
list<integer> timeComponent = new list<integer>();
timeComponent.add(Integer.valueOf(d2[0]));
timeComponent.add(Integer.valueOf(d2[1]));
timeComponent.add(Integer.valueOf(d2[2].left(2)));
String t = d2[2].substringBetween('T','.');
list<String> time1 = t.split(':');
timeComponent.add(Integer.valueOf(time1[0]));
timeComponent.add(Integer.valueOf(time1[1]));
timeComponent.add(Integer.valueOf(time1[2]));
Datetime dt = Datetime.newInstance(timeComponent[0],timeComponent[1],timeComponent[2],timeComponent[3],timeComponent[4],timeComponent[5]);
sObj.put(fieldName, dt);
}
//
else if (valueType == Schema.DisplayType.Percent || valueType == Schema.DisplayType.Currency)
sObj.put(fieldName, svalue == '' ? null : Decimal.valueOf(svalue));
else if (valueType == Schema.DisplayType.Double)
sObj.put(fieldName, svalue == '' ? null : Double.valueOf(svalue));
else if (valueType == Schema.DisplayType.Integer)
sObj.put(fieldName, Integer.valueOf(svalue));
else if (valueType == Schema.DisplayType.Base64)
sObj.put(fieldName, Blob.valueOf(svalue));
else
sObj.put(fieldName, svalue);
}
else
sObj.put(fieldName, value);
}
}
updateList.add(sObj);
}
update updateList;
//return sobList;
}
public class DataTableWrapper {
@AuraEnabled
public List<LabelDescriptionWrapper> ldwList;
@AuraEnabled
public List<sObject> sobList;
@AuraEnabled
public List<String> fieldsList;
@AuraEnabled
public Integer totalCount;
}
public class LabelDescriptionWrapper {
@AuraEnabled
public String label;
@AuraEnabled
public String fieldName;
@AuraEnabled
public String type;
@AuraEnabled
public boolean sortable;
@AuraEnabled
public boolean editable;
@AuraEnabled
public TypeAttributes typeAttributes;
public LabelDescriptionWrapper(String labelTemp, String fieldNameTemp, String typeTemp, boolean sortableTemp, boolean editableTemp,TypeAttributes typeAttributesTemp) {
label = labelTemp;
fieldName = fieldNameTemp;
type = typeTemp;
sortable = sortableTemp;
editable = editableTemp;
typeAttributes = typeAttributesTemp;
}
}
public class TypeAttributes {
@AuraEnabled
public List<Actions> rowActions;
public typeAttributes(List<Actions> rowActionsTemp) {
rowActions = rowActionsTemp;
}
}
public class Actions {
@AuraEnabled
public String label;
@AuraEnabled
public String name;
public Actions(String labelTemp, String nameTemp) {
label = labelTemp;
name = nameTemp;
}
}
}
<aura:component controller="DataTableController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
<!-- attributes -->
<aura:attribute name="objectName" type="String" default="Account"/>
<aura:attribute name="fieldsString" type="String" default="Name,Phone,Email,Website"/>
<aura:attribute name="fieldsList" type="List" default="[]"/>
<aura:attribute name="columns" type="List" default="[]"/>
<aura:attribute name="data" type="List" default="[]"/>
<aura:attribute name="selectedData" type="List" default="[]"/>
<aura:attribute name="keyField" type="String" default="id"/>
<aura:attribute name="initialRows" type="Integer" default="5"/>
<aura:attribute name="selectedRowsCount" type="Integer" default="0"/>
<aura:attribute name="enableInfiniteLoading" type="Boolean" default="true"/>
<aura:attribute name="rowsToLoad" type="Integer" default="50"/>
<aura:attribute name="totalNumberOfRows" type="Integer" default="3000"/>
<aura:attribute name="loadMoreStatus" type="String" default=""/>
<aura:attribute name="sortedBy" type="String" default="Id"/>
<aura:attribute name="sortedDirection" type="String" default="ASC"/>
<aura:attribute name="inlineEdit" type="boolean" default="true"/>
<aura:attribute name="enableColAction" type="boolean" default="true"/>
<aura:attribute name="showRowNumber" type="boolean" default="true"/>
<aura:attribute name="hideCheckboxColumn" type="boolean" default="false"/>
<aura:attribute name="maxRowSelection" type="Integer" default="50"/>
<aura:attribute name="tableHeight" type="Integer" default="450"/>
<aura:attribute name="errors" type="Object" default="[]"/>
<aura:attribute name="pageReference" type="Object"/>
<lightning:navigation aura:id="navService"/>
<lightning:notificationsLibrary aura:id="notifLib"/>
<!-- handlers-->
<aura:handler name="init" value="{! this }" action="{! c.init }"/>
<div class="slds-is-relative">
<!-- the container element determine the height of the datatable -->
<div style="{!'height:'+v.tableHeight+'px'}">
<lightning:datatable aura:id="dataTable"
columns="{! v.columns }"
data="{! v.data }"
keyField="{! v.keyField }"
showRowNumberColumn="{! v.showRowNumber }"
sortable = "true"
editable = "true"
onsort = "{! c.updateColumnSorting }"
sortedBy="{!v.sortedBy}"
sortedDirection="{!v.sortedDirection}"
onrowselection="{! c.updateSelectedRow }"
maxRowSelection="{! v.maxRowSelection }"
enableInfiniteLoading="{! v.enableInfiniteLoading }"
onloadmore="{! c.loadMoreData }"
onrowaction="{! c.handleRowAction }"
errors="{! v.errors }"
draftValues="{! v.draftValues }"
onsave="{! c.handleSaveEdition }"
/><!-- hideCheckboxColumn = "{! c.hideCheckboxColumn }" -->
</div>
{! v.loadMoreStatus }
</div>
</aura:component>
({
init: function (cmp, event, helper) {
console.log( cmp.get("v.data").length );
helper.initData(cmp, event, cmp.get("v.data").length);
},
updateSelectedRow: function (cmp, event) {
var selectedRows = event.getParam('selectedRows');
cmp.set('v.selectedRowsCount', selectedRows.length);
cmp.set('v.selectedData', selectedRows);
console.log( cmp.get('v.selectedData') );
},
resetRows: function (cmp, event, helper) {
cmp.set('v.data', []);
helper.initData(cmp, event, cmp.get("v.data").length);
},
loadMoreData: function (cmp, event, helper) {
var rowsToLoad = cmp.get('v.rowsToLoad');
event.getSource().set("v.isLoading", true);
cmp.set('v.loadMoreStatus', 'Loading');
helper.fetchData(cmp, event, cmp.get("v.data").length);
},
updateColumnSorting: function (cmp, event, helper) {
var fieldName = event.getParam('fieldName');
var sortDirection = event.getParam('sortDirection');
// assign the latest attribute with the sorted column fieldName and sorted direction
cmp.set("v.sortedBy", fieldName);
cmp.set("v.sortedDirection", sortDirection);
cmp.set('v.data', []);
event.getSource().set("v.isLoading", true);
cmp.set('v.loadMoreStatus', 'Loading');
helper.initData(cmp, event, cmp.get("v.data").length);
},
handleRowAction: function (cmp, event, helper) {
var action = event.getParam('action');
var row = event.getParam('row');
switch (action.name) {
case 'Edit':
helper.editRecord(cmp, row);
break;
case 'View':
helper.viewRecord(cmp, row);
break;
case 'Delete':
helper.deleteRecord(cmp, row);
break;
default:
helper.viewRecord(cmp,row);
break;
}
},
handleSaveEdition: function (cmp, event, helper) {
var draftValues = event.getParam('draftValues');
var data = cmp.get('v.data');
helper.saveRecords(cmp, event, helper, data, draftValues);
},
})
({
initData: function (cmp, event, numberOfRecords) {
var action = cmp.get("c.initRecords");
action.setParams({
ObjectName : cmp.get("v.objectName"),
fieldNamesStr : cmp.get("v.fieldsString"),
Orderby : cmp.get("v.sortedBy"),
OrderDir : cmp.get("v.sortedDirection"),
inlineEdit: cmp.get("v.inlineEdit"),
enableColAction: cmp.get("v.enableColAction")
});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
console.log(response.getReturnValue().ldwList);
cmp.set("v.columns", response.getReturnValue().ldwList);
cmp.set("v.data", response.getReturnValue().sobList);
cmp.set("v.fieldsList", response.getReturnValue().fieldsList);
cmp.set("v.totalNumberOfRows", response.getReturnValue().totalCount);
cmp.set('v.loadMoreStatus', '');
event.getSource().set("v.isLoading", false);
}
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("Unknown error");
}
}
});
$A.enqueueAction(action);
},
fetchData: function (cmp, event, numberOfRecords) {
//var dataPromise;
var data = cmp.get("v.data");
var dataSize = cmp.get("v.data").length;
var lastId = data[dataSize - 1].Id;
var action = cmp.get("c.getsObjectRecords");
action.setParams({
ObjectName : cmp.get("v.objectName"),
fieldNameSet : cmp.get("v.fieldsList"),
LimitSize : 50,
recId : lastId,
Orderby : cmp.get("v.sortedBy"),
OrderDir : cmp.set("v.sortedDirection")
});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
if (cmp.get('v.data').length >= cmp.get('v.totalNumberOfRows')) {
cmp.set('v.enableInfiniteLoading', false);
cmp.set('v.loadMoreStatus', 'No more data to load');
} else {
var currentData = cmp.get('v.data');
var newData = currentData.concat(response.getReturnValue());
cmp.set('v.data', newData);
cmp.set('v.loadMoreStatus', '');
}
event.getSource().set("v.isLoading", false);
}
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("Unknown error");
}
}
});
$A.enqueueAction(action);
},
sortData: function (cmp, fieldName, sortDirection) {
var data = cmp.get("v.data");
var reverse = sortDirection !== 'asc';
//sorts the rows based on the column header that's clicked
data.sort(this.sortBy(fieldName, reverse))
cmp.set("v.data", data);
},
sortBy: function (field, reverse, primer) {
var key = primer ?
function(x) {return primer(x[field])} :
function(x) {return x[field]};
//checks if the two rows should switch places
reverse = !reverse ? 1 : -1;
return function (a, b) {
return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
}
},
editRecord: function (cmp, row) {
var navService = cmp.find("navService");
var pageReference = {
type: 'standard__recordPage',
attributes: {
"recordId": row.Id,
"objectApiName": cmp.get("v.objectName"),
"actionName": "edit"
}
}
navService.navigate(pageReference);
},
viewRecord : function(cmp, row) {
var navService = cmp.find("navService");
console.log(row);
var pageReference = {
type: 'standard__recordPage',
attributes: {
"recordId": row.Id,
"objectApiName": cmp.get("v.objectName"),
"actionName": "view"
}
}
navService.navigate(pageReference);
},
deleteRecord : function(cmp, row) {
var action = cmp.get("c.deleteSObject");
action.setParams({
"sob":row
});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var rows = cmp.get('v.data');
var rowIndex = rows.indexOf(row);
rows.splice(rowIndex, 1);
cmp.set('v.data', rows);
/* var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
"title": "Success!",
"message": "Record deleted.",
"type": "success"
});
toastEvent.fire();
*/
cmp.find('notifLib').showNotice({
"variant": "info",
"header": "Success!",
"message": "Record deleted.",
closeCallback: function() {
}
});
}
else if (state === "ERROR") {
// handle error
var errorMsg = '';
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
errorMsg = errors[0].message;
}
if (errors[0] && errors[0].pageErrors && errors[0].pageErrors[0].message) {
errorMsg += errors[0].pageErrors[0].message;
}
}
cmp.find('notifLib').showNotice({
"variant": "error",
"header": "Something has gone wrong!",
"message": errorMsg,
closeCallback: function() {
}
});
/*
var errors = response.getError();
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
"title": "error",
"message": errorMsg,
"type": "error"
});
toastEvent.fire();*/
}
});
$A.enqueueAction(action);
},
saveRecords : function(cmp, event, helper, data, draftValues) {
var action = cmp.get("c.updateRecords");
var draftValuesStr = JSON.stringify(draftValues);
action.setParams({
"sobList":data,
"updateObjStr" : draftValuesStr,
"objectName" : cmp.get("v.objectName")
});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
cmp.set('v.errors', []);
cmp.set('v.draftValues', []);
helper.initData(cmp, event, 50);
}
else if (state === "ERROR") {
// handle error
var errorMsg = '';
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
errorMsg = errors[0].message;
}
if (errors[0] && errors[0].pageErrors && errors[0].pageErrors[0].message) {
errorMsg += errors[0].pageErrors[0].message;
}
}
cmp.find('notifLib').showNotice({
"variant": "error",
"header": "Something has gone wrong!",
"message": errorMsg,
closeCallback: function() {
}
});
cmp.set('v.errors', errorMsg);
}
});
$A.enqueueAction(action);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment