Skip to content

Instantly share code, notes, and snippets.

@vermadhirendra28
Created August 10, 2019 12:04
Show Gist options
  • Save vermadhirendra28/e169b18eeb53f4f0257c0990ead393ec to your computer and use it in GitHub Desktop.
Save vermadhirendra28/e169b18eeb53f4f0257c0990ead393ec to your computer and use it in GitHub Desktop.
Dynamic Lightning Datatable
/**
* Desc: A class which can be used to create a dynamic lightning datatable only by passing the object name and fields name
* that we need to display as column for the Datatable
**/
public class CreateDynamicDatatable {
/**
* Wrapper that will be used by the lightning datatable as columns
*/
public with sharing class DynamicDataTableColumn {
@AuraEnabled public String type{get; set;}
@AuraEnabled public String fieldName{get; set;}
@AuraEnabled public String label{get; set;}
public DynamicDataTableColumn(String type, String fieldName, String label) {
this.type = type;
this.fieldName = fieldName;
this.label = label;
}
}
/**
* A wrapper that represents the collection of column, object name and the list of records data that need
* to display in the lightning table
**/
public with sharing class DynamicDataTable{
public String strObjectlabel{get;set;}
public String strObjectApiName{get;set;}
public list<SObject> listObjectData{get;set;}
public List<DynamicDataTableColumn> listDataColumn{get;set;}
public DynamicDataTable(String p_strObjectlabel,String p_strObjectApiName,
list<SObject> p_listObjectData,List<DynamicDataTableColumn> p_listDataColumn){
this.strObjectlabel = p_strObjectlabel;
this.strObjectApiName = p_strObjectApiName;
this.listObjectData = p_listObjectData;
this.listDataColumn = p_listDataColumn;
}
}
/***
* Desc: a method which recieves the object name along with its fields api
* and returns the label for that object and its provided fields
**/
public static map<String,List<DynamicDataTableColumn>> fetchlabels(map<string,string> p_mapObjectWithField){
map<String,String> mapDataWithlabel = new map<String,String>();
map<String,List<DynamicDataTableColumn>> mapObjectWithColumns = new map<String,List<DynamicDataTableColumn>>();
for(String strObjectName : p_mapObjectWithField.keyset()){
Map<String, Schema.SObjectType> global_describe = Schema.getGlobalDescribe();
Map<String, Schema.SObjectField> object_fields_map = global_describe.get(strObjectName).getDescribe().fields.getMap();
List<DynamicDataTableColumn> columns = new List<DynamicDataTableColumn>();
for(String strFieldApiLabel :p_mapObjectWithField.get(strObjectName).split(',')){
system.debug('datatypevlaue ***'+object_fields_map.get(strFieldApiLabel).getDescribe().getType());
String fieldLabel = object_fields_map.get(strFieldApiLabel).getDescribe().getLabel();
String fieldType = String.valueOf(object_fields_map.get(strFieldApiLabel).getDescribe().getType());
DynamicDataTableColumn newCell = new DynamicDataTableColumn(
convertToLightningDataType(fieldType),
String.escapeSingleQuotes(strFieldApiLabel),
fieldLabel);
columns.add(newCell);
}
mapObjectWithColumns.put(strObjectName,columns);
}
system.debug('columns***'+mapObjectWithColumns);
return mapObjectWithColumns;
}
/**
* Desc: A method that fetch all the data that needs to be displayed on the lightning datatable
**/
@AuraEnabled
public static map<String,Object> getTableData(String strObjectName,
String strApiFields,
String strPageRecordSize){
map<String,String> mapObjectWithField = new map<String,String>();
map<String,Object> mapData = new map<String,Object>();
system.debug('strObjectName***'+strObjectName);
system.debug('listGridcolumn***'+ strApiFields);
mapObjectWithField.put(strObjectName,strApiFields);
map<String,List<DynamicDataTableColumn>> mapObjectWithColumns = fetchlabels(mapObjectWithField);
system.debug('mapObjectWithColumns***'+mapObjectWithColumns);
List<DynamicDataTableColumn> listSelectedGridcol = mapObjectWithColumns.get(strObjectName);
list<SObject> listObject = new List<SObject>();
String strQuery = 'Select Id';
for(DynamicDataTableColumn objCell: mapObjectWithColumns.get(strObjectName)){
strQuery = strQuery +','+ objCell.fieldName;
}
strQuery = strQuery + ' From ' +strObjectName +' limit ' +strPageRecordSize ;
system.debug('strQuery***'+strQuery);
for(SObject o : Database.query(strQuery)){
listObject.add(o);
}
system.debug(listObject);
map<String,String> mapObjectWithLabel = fetchObjectRelatedLabel(mapObjectWithField);
DynamicDataTable objNewData = new DynamicDataTable(mapObjectWithLabel.get(strObjectName),
strObjectName,
listObject,
listSelectedGridcol);
mapData.put('DataFetched',JSON.serialize(objNewData));
return mapData;
}
/**
* Desc: A method to fetch the object Label from the api name passed as a parameter to the method
**/
public static map<String,String> fetchObjectRelatedLabel(map<String,String> mapSobjectApiWithFields){
map<String,String> mapObjectApiWithLabel = new map<String,String>();
Map <String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
for(String objApiName : mapSobjectApiWithFields.keySet()){
String strObjectLabel = String.valueOf(schemaMap.get(objApiName).getDescribe().getLabel());
mapObjectApiWithLabel.put(objApiName,strObjectLabel);
}
return mapObjectApiWithLabel;
}
/**
* Desc: A method to used to convert the apex datatype to lightning data type
**/
public static String convertToLightningDataType(String apexFieldDataType) {
String lightningDataType = 'text'; // default
apexFieldDataType = apexFieldDataType.toLowerCase();
Map<String, Set<String>> lightningToApexDataTypeMap = new Map<String, Set<String>>{
'text' => new Set<String>{'address', 'id', 'phone', 'email', 'string', 'textarea'},
'date' => new Set<String>{'date', 'datetime'},
'number' => new Set<String>{'double', 'integer'},
'percent' => new Set<String>{'percent'},
'currency' => new Set<String>{'currency'},
'url' => new Set<String>{'url'}
};
for (String type : lightningToApexDataTypeMap.keySet()) {
if (lightningToApexDataTypeMap.get(type).contains(apexFieldDataType)) {
lightningDataType = type;
break;
}
}
return lightningDataType;
}
}
/** code for dynamicLightning DataTable **/
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global"
controller="CreateDynamicDatatable">
<aura:attribute name="strObjectApiName" type="String" default="Account" access="global"/>
<aura:attribute name="fields" type="String"
default="Name" access="global"/>
<aura:attribute name="fetchedSelectedRecords" type="Object" access="global"/>
<aura:attribute name="selectedObjectRecList" type="list" />
<aura:attribute name="noOfRecordsOnPage" type="integer" default="100" access="global"/>
<aura:attribute name="displayTable" type="boolean" default="true" />
<aura:attribute name="Spinner" type="boolean" default="false"/>
<!--handler method -->
<aura:handler event="aura:waiting" action="{!c.showSpinner}"/>
<aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/>
<aura:handler name="init" value="{!this}" action="{!c.init}" />
<!-- Register events -->
<aura:registerEvent name="callPassDynamicSelectedRecEvt" type="c:passDynamicSelectedRec"/>
<div class="container">
<!--loading spinner start... style=Brand Medium (blue dots)-->
<aura:if isTrue="{!v.Spinner}">
<div aura:id="spinnerId" class="slds-spinner_container">
<div class="slds-spinner--brand slds-spinner slds-spinner--large slds-is-relative" role="alert">
<span class="slds-assistive-text">Loading</span>
<div class="slds-spinner__dot-a"></div>
<div class="slds-spinner__dot-b"></div>
</div>
</div>
</aura:if>
<aura:if isTrue="{!v.displayTable}">
<div class="slds-page-header">
<article class="slds-card">
<div class="slds-card__header slds-grid">
<header class="slds-media slds-media_center slds-has-flexi-truncate">
<div class="slds-media__figure">
<span class="slds-icon_container slds-icon-standard-account" title="{!v.fetchedSelectedRecords.strObjectlabel}">
<lightning:icon iconName="utility:custom1" size="medium"/>
<span class="slds-assistive-text">{!v.fetchedSelectedRecords.strObjectlabel}</span>
</span>
</div>
<div class="slds-media__body">
<h2 class="slds-card__header-title">
<a href="javascript:void(0);" class="slds-card__header-link slds-truncate" title="Accounts">
<span>{!v.fetchedSelectedRecords.strObjectlabel}</span>
</a>
</h2>
</div>
</header>
</div>
<div class="slds-card__body slds-card__body_inner">
<lightning:datatable data="{!v.fetchedSelectedRecords.listObjectData}"
columns="{!v.fetchedSelectedRecords.listDataColumn}"
keyField="Id"
onrowselection="{!c.handleSelect}"/>
</div>
</article>
<div style="padding-top:2%;text-align:center">
<button class="slds-button slds-button_brand" onclick="{!c.getSelectedRec}">
Get Seleced Records
</button>
</div>
</div>
</aura:if>
<aura:if isTrue ="{!!displayTable}">
<div class="messagecontainer center fontsize">
</div>
</aura:if>
</div>
</aura:component>
/**End of lightning component**/
/** lighting controller.js**/
({
init : function(component, event, helper) {
helper.getTableData(component,event);
},
handleSelect:function(component,event,helper){
try{
helper.createSelectedReclist(component,event);
}catch(e){
console.error(e);
}
},
getSelectedRec: function(component,event,helper){
try{
helper.fetchSelectedRecordList(component,event);
}catch(e){
console.error(e);
}
},
// this function automatic call by aura:waiting event
showSpinner: function(component, event, helper) {
// make Spinner attribute true for display loading spinner
component.set("v.Spinner", true);
},
// this function automatic call by aura:doneWaiting event
hideSpinner : function(component,event,helper){
// make Spinner attribute to false for hide loading spinner
component.set("v.Spinner", false);
}
})
/** end of dynamicLightningDataTablecontroller.js code **/
/**Begining of dynamicLightningDataTableHelper.js code **/
({
getTableData : function(cmp,event) {
var limitRecordsize = cmp.get("v.noOfRecordsOnPage");
var execAction = cmp.get("c.getTableData");
execAction.setParams({
"strObjectName":cmp.get("v.strObjectApiName"),
"strApiFields" :cmp.get("v.fields"),
"strPageRecordSize":limitRecordsize
});
this.serverSideCall(cmp,execAction).then(
function(res) {
console.log(res);
var queriedResult = JSON.parse(res.DataFetched);
if(queriedResult.listObjectData.length > 0){
cmp.set("v.fetchedSelectedRecords",queriedResult);
}
}).catch(
function(error) {
console.log(error);
cmp.set("v.displayTable",false);
}
);
},
createSelectedReclist: function(component,event){
var selectedRows = event.getParam('selectedRows');
let listObjectRec = [] ;
if(selectedRows.length > 0){
for(var i = 0;i<selectedRows.length;i++){
listObjectRec.push(selectedRows[i].Id);
}
}
console.log('list of selectedrec ***'+listObjectRec);
component.set('v.selectedObjectRecList',listObjectRec);
},
/**
* A javascript method to pass the selected recordlist back to the parent component
**/
fetchSelectedRecordList: function(component,event){
var selectedReclist = component.get("v.selectedObjectRecList");
var cmpEvent = component.getEvent("callPassDynamicSelectedRecEvt");
cmpEvent.setParams({"selectedRecordId" : selectedReclist});
cmpEvent.fire();
},
/**
* Inclusion of Promise then to handle the response recieved from controller in a more appropriate way
**/
serverSideCall : function(component,action) {
return new Promise(function(resolve, reject) {
action.setCallback(this,
function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var result = response.getReturnValue();
resolve(result);
} else {
reject(new Error(response.getError()));
}
});
$A.enqueueAction(action);
});
},
})
/**End of dynamicLightningDataTableHelper.js code **/
<aura:event type="COMPONENT" description="Event template" >
<aura:attribute name="selectedRecordId" type="list" />
</aura:event>
<!-- parent component which will be using the dynamic lightning datatable -->
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,
flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,
force:lightningQuickAction" access="global" >
<aura:attribute name="strObjectAPIName" type="String" default="Account"/>
<aura:attribute name="strFieldsAPIName" type="String" default="Name,Phone" />
<aura:attribute name="listSelectedObjectRecId" type="list" />
<aura:attribute name="noOfRecLimit" type="integer" default="5"/>
<aura:attribute name="displaySelectedRecid" type="boolean" default="false"/>
<!--handle the event fired from the child components -->
<aura:handler name="callPassDynamicSelectedRecEvt" event="c:passDynamicSelectedRec" action="{!c.handleSelectedRecordEvent}"/>
<div class="container">
<c:dynamicLightningDataTable strObjectApiName="{!v.strObjectAPIName}"
fields="{!v.strFieldsAPIName}" noOfRecordsOnPage="{!v.noOfRecLimit}"/>
<aura:if isTrue="{!v.displaySelectedRecid}">
<aura:iteration items="{!v.listSelectedObjectRecId}" var="RecId">
Selected RecordIds : {!RecId}<br/>
</aura:iteration>
</aura:if>
</div>
</aura:component>
<!--end of aura component -->
/**code for UseDynamicLightningDataTableController.js file **/
({
handleSelectedRecordEvent : function(component, event, helper) {
var selectedObjectReclist = event.getParam("selectedRecordId");
// set the handler attributes based on event data
component.set("v.listSelectedObjectRecId", selectedObjectReclist);
component.set("v.displaySelectedRecid",true);
}
})
/** end of lightningcontroller.js file **/
@vermadhirendra28
Copy link
Author

Implementation of Dynamic lightning datatable which returns selected records Id to perform further action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment