Dynamic component to retrieve quick report

If we need to view some of data based on some criteria from an object by clicking a Button, we can use this custom component. The component is dynamic and works for any object in Salesforce without modifying the component.

Introduction:

If we need to view some of data based on some criteria from an object by clicking a Button, we can use this custom component. The component is dynamic and works for any object in Salesforce without modifying the component.

Component: [Parent Component]

<aura:component implements = “force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction,force:hasSObjectName”

access = “global”

controller = “DynamicClass” >

<!– Attributes used in this component –>

<aura:attribute name = “sobjecttype” type = “String” default = “{!v.sObjectName}”

<aura:attribute name = “sobjectField” type = “List” default = “[]” />

<aura:attribute name = “sobject” type = “List” default = “[]” />

<aura:attribute name = “selectedObject” type = “List” default = “[]” />

<aura:attribute name = “isOpenChooseBox” type = “boolean” default = “false” />

<aura:attribute name = “isOpenFieldBox” type = “boolean” default = “false” />

<aura:attribute name = “isResultBox” type = “boolean” default = “false” />

<aura:attribute name = “isFilterBox” type = “boolean” default = “false” />

<aura:attribute name = “selectedItem” type = “String” />

<aura:attribute name = “selectedFields” type = “List” default = “[]” />

<aura:attribute name = “resultList” type = “List” default = “[]” />

<aura:attribute name = “showSpinner” type = “Boolean” default = “false” />

<aura:attribute name = “datatypefield” type = “List” default = “[]” />

<!– Notification Library –>

<lightning:notificationsLibrary aura:id=”notifLib” />

<!– Lightning Button –>

<lightning:button variant = “brand” label = “Quick Report” title = “Click Here” onclick = “{! c.handleObjectItself }” />

<aura:if isTrue = “{!v.isOpenFieldBox}”>

<section role = “dialog” tabindex = “-1” aria-labelledby = “modal-heading-01” aria-modal = “true” aria-describedby = “modal-content-id-1” class = “slds-modal slds-fade-in-open”>

<div class = “slds-modal__container”>

<header class = “slds-modal__header”>

<lightning:buttonIcon iconName = “utility:close”

onclick = “{! c.closeModelBox }”

alternativeText = “close”

variant = “bare-inverse”

class = “slds-modal__close” />

<h2 id = “modal-heading-01” class = “slds-text-heading_medium slds-hyphenate”>Select a Field to be Shown as Header of Report</h2>

</header>

<div class = “slds-modal__content slds-p-around_medium” id=”modal-content-id-1″>

<table>

<th></th>

<tbody>

<aura:iteration items = “{!v.sobjectField}” var = “a”>

<tr>

<td><lightning:input type = “checkbox” name = “{!a}” value = “{!a}” onclick = “{!c.onClick}”></lightning:input></td>

<td>{!a}</td>

</tr>

</aura:iteration>

</tbody>

<aura:if isTrue = “{!v.showSpinner}”>

<lightning:spinner aura:id = “spinner” variant = “brand” alternativeText = “Rates” size = “medium” />

</aura:if>

</table>

</div>

<footer class = “slds-modal__footer”>

<lightning:button variant = “neutral”

label = “Previous”

title = “Previous”

onclick = “{! c.clickPrevious}”/>

<lightning:button variant = “neutral”

label = “Next”

title = “Next”

onclick = “{! c.clickNext}”/>

<lightning:button variant = “neutral”

label = “Cancel”

title = “Cancel”

onclick = “{! c.closeModelBox }”/>

</footer>

</div>

</section>

</aura:if>

<aura:if isTrue = “{!v.isFilterBox}”>

<section role = “dialog” tabindex = “-1” aria-labelledby = “modal-heading-01” aria-modal = “true” aria-describedby = “modal-content-id-1” class = “slds-modal slds-fade-in-open”>

<div class = “slds-modal__container”>

<header class = “slds-modal__header”>

<lightning:buttonIcon iconName = “utility:close”

onclick = “{! c.closeFilterBox }”

alternativeText = “close”

variant = “bare-inverse”

class = “slds-modal__close”/>

<h2 id = “modal-heading-01” class = “slds-text-heading_medium slds-hyphenate”>Please Apply Filter Criteria For Report</h2>

</header>

<div class = “slds-modal__content slds-p-around_medium” id = “modal-content-id-1”>

<div class = “row”>

<div class=”slds-grid slds-gutters”>

<div class=”slds-col”>

<lightning:select aura:id=”recordList” label=”{!v.sobjecttype}” >

<option value=””></option>

<aura:iteration items=”{! v.datatypefield}” var=”textField” >

<option value=”{! textField }”> {! textField } </option>

</aura:iteration>

</lightning:select>

</div>

<div class=”slds-col”>

<lightning:input name = “input1” aura:id = “selectIs” placeholder = “type the name of the records …” label = “Enter Some Text” />

</div>

</div>

<lightning:input type = “number” name = “input1” aura:id = “select” placeholder = “type the number of records…” label = “Enter a number” />

</div>

</div>

<footer class = “slds-modal__footer”>

<lightning:button variant = “neutral”

label = “Finish”

title = “Finish”

onclick = “{! c.finish}”/>

<lightning:button variant = “neutral”

label = “Previous”

title = “Previous”

onclick = “{! c.clickPreviousone}”/>

<lightning:button variant = “neutral”

label = “Cancel”

title = “Cancel”

onclick = “{! c.closeFilterBox}”/>

</footer>

</div>

<aura:if isTrue = “{!v.showSpinner}”>

<lightning:spinner aura:id = “spinner” variant = “brand” alternativeText = “Rates” size = “medium” />

</aura:if>

</section>

</aura:if>

<aura:if isTrue = “{!v.isResultBox}”>

<section role = “dialog” tabindex = “-1” aria-labelledby = “modal-heading-01” aria-modal = “true” aria-describedby = “modal-content-id-1” class = “slds-modal slds-fade-in-open”>

<div class = “slds-modal__container”>

<header class = “slds-modal__header”>

<lightning:buttonIcon iconName = “utility:close”

onclick = “{! c.closeResultBox }”

alternativeText = “close”

variant = “bare-inverse”

class = “slds-modal__close”/>

</header>

<div class = “slds-modal__content slds-p-around_medium” id = “modal-content-id-1″>

<table class=”slds-table slds-table_bordered slds-table_cell-buffer slds-table_striped”>

<thead>

<tr></tr>

<tr class=”slds-text-title_caps”>

<aura:iteration items=”{!v.selectedFields}” var=”fieldName”>

<th scope=”col”>

<div class=”slds-truncate”>{!fieldName}</div>

</th>

</aura:iteration>

</tr>

</thead>

<tbody>

<aura:iteration items = “{!v.resultList}” var = “result”>

<tr>

<aura:iteration items = “{!v.selectedFields}” var = “fieldName”>

<td class = “slds-truncate”>

<c:childcmp object = “{!result}” fieldName = “{!fieldName}”/>

</td>

</aura:iteration>

</tr>

</aura:iteration>

</tbody>

</table>

</div>

<footer class = “slds-modal__footer”>

<lightning:button variant = “neutral”

label = “Cancel”

title = “Cancel”

onclick = “{! c.closeResultBox}”/>

</footer>

</div>

<aura:if isTrue = “{!v.showSpinner}”>

<lightning:spinner aura:id = “spinner” variant = “brand” alternativeText = “Rates” size = “medium” />

</aura:if>

</section>

</aura:if>

</aura:component>

 

Controller:

({

handleObjectItself : function(cmp, evnt, help) {

cmp.set(“v.showSpinner”,true);

help.generateObjectField(cmp, evnt, help);

},

closeModelBox : function(cmp, evnt, help) {

cmp.set(“v.isOpenFieldBox”, false);

},

handleGroupChange: function (cmp, evnt) {

var value = evnt.getParam(‘value’);

cmp.set(‘v.selection’, value);

},

handleBeforeSelect : function (cmp, evnt) {

cmp.set(‘v.selectedItem’, evnt.getParam(‘name’));

},

handleSelect : function (cmp, evnt,help) {

help.generateRelatedObjectField(cmp, evnt, help);

},

onClick : function (cmp, evnt) {

var tempHaulerChangedField = [];

var data = cmp.get(“v.selectedFields”);

if(data)

tempHaulerChangedField = data;

tempHaulerChangedField.push(evnt.getSource().get(“v.value”));

var uniqueArray = Array.from(new Set(tempHaulerChangedField));

cmp.set(“v.selectedFields”,uniqueArray);

},

clickNext : function (cmp, evnt,help) {

var action = cmp.get(“c.getStringField”);

cmp.set(“v.showSpinner”,true);

action.setParams({

“sObjectType” : cmp.get(“v.sobjecttype”),

});

action.setCallback(this,function(response){

var state = response.getState() ;

if(state == ‘SUCCESS’){

var res = response.getReturnValue();

if(!res.hasError){

if(!$A.util.isEmpty(res.sdata) && res.sdata.length > 0){

cmp.set(“v.datatypefield”,res.sdata);

cmp.set(“v.isOpenFieldBox”, false);

cmp.set(“v.isFilterBox”,true);

cmp.set(“v.showSpinner”,false);

}

}else{

var toastEvent = $A.get(“e.force:showToast”);

toastEvent.setParams({

“title”: “Error!”,

“message”: response.message,

“type” : “error”,

});

toastEvent.fire();

cmp.set(“v.showSpinner”,false);

}

}

});

$A.enqueueAction(action);

},

closeResultBox : function (cmp, evnt,help) {

cmp.set(“v.isResultBox”, false);

},

closeFilterBox : function (cmp, evnt,help){

cmp.set(“v.isFilterBox”, false);

},

clickPrevious : function (cmp,evnt,help){

cmp.set(“v.isOpenChooseBox”,true);

cmp.set(“v.isOpenFieldBox”,false);

},

clickPreviousone : function(cmp,evnt,help){

cmp.set(“v.selectedFields”,null);

cmp.set(“v.isOpenFieldBox”,true);

cmp.set(“v.isFilterBox”,false);

},

finish : function(cmp,evnt,help){

var sObjectType = cmp.get(“v.sobjecttype”);

var fieldsList = cmp.get(“v.selectedFields”);

var Limits = cmp.find(“select”).get(“v.value”);

var Types = cmp.find(“selectIs”).get(“v.value”);

var field = cmp.find(“recordList”).get(“v.value”);

if(Types != ” && field == ”)

cmp.find(‘notifLib’).showNotice({

“variant” : “Information”,

“header” : “Please Check the filter criteria!”,

“message” : “Please select the field to filter”,

});

else

help.goPage(cmp,evnt,sObjectType,fieldsList,Limits,Types,field);

},

AddNewRow : function(cmp,evnt,help){

cmp.getEvent(“AddRowEvt”).fire();

},

 

})

Helper:

({

generateObjectField : function(cmp, evnt, help) {

var action = cmp.get(“c.getRelatedSobjectName”);

cmp.set(“v.showSpinner”,true);

action.setParams({

“sObjectType” : cmp.get(“v.sobjecttype”),

});

action.setCallback(this,function(response){

var state = response.getState() ;

if(state == ‘SUCCESS’){

var res = response.getReturnValue();

if(!res.hasError){

if(!$A.util.isEmpty(res.sdata) && res.sdata.length > 0){

cmp.set(“v.sobjectField”,res.sdata);

cmp.set(“v.isOpenFieldBox”, true);

cmp.set(“v.showSpinner”,false);

}

}else{

var toastEvent = $A.get(“e.force:showToast”);

toastEvent.setParams({

“title” : “Error!”,

“message” : response.message,

“type” : “error”,

});

toastEvent.fire();

cmp.set(“v.showSpinner”,false);

}

}

});

$A.enqueueAction(action);

},

 

goPage : function(cmp,evnt,sObjectType,fieldsList,Limits,Types,field){

var action = cmp.get(“c.getFields”);

cmp.set(“v.showSpinner”,true);

action.setParams({

“sObjectType” : sObjectType,

“fieldsList” : fieldsList,

“Limits” : Limits,

“Types” : Types,

“field” : field,

});

action.setCallback(this,function(response){

var state = response.getState() ;

if(state == ‘SUCCESS’){

var res = response.getReturnValue();

if(!res.hasError){

if(!$A.util.isEmpty(res.sObjectData) && res.sObjectData.length > 0){

cmp.set(“v.resultList”,res.sObjectData);

cmp.set(“v.isOpenFieldBox”, false);

cmp.set(“v.isResultBox”, true);

cmp.set(“v.showSpinner”,false);

}else{

cmp.find(‘notifLib’).showNotice({

“variant” : “Information”,

“header” : “No Records found!”,

“message” : “Please Check the filter criteria.”,

});

cmp.set(“v.showSpinner”,false);

}

}else{

var toastEvent = $A.get(“e.force:showToast”);

toastEvent.setParams({

“title” : “Error!”,

“message” : response.message,

“type” : “error”,

});

toastEvent.fire();

cmp.set(“v.showSpinner”,false);

}

}

});

$A.enqueueAction(action);

},

})

Component : [Child Component]

<aura:component implements = “force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction”

access = “global” >

<aura:attribute name = “object” type = “Object” default = “” />

<aura:attribute name = “fieldName” type = “String” default = “” />

<aura:attribute name = “fieldValue” type = “String” access = “private” />

<aura:attribute name = “fields” type = “List” default = “[]” />

<aura:handler name = “init” value = “{!this}” action = “{!c.doInit}” />

<ui:outputText value=”{!v.fieldValue}”/>

</aura:component>

Controller:

({

doInit : function(component, event, helper) {

var rowData = component.get(‘v.object’);

var field = component.get(‘v.fieldName’);

component.set(“v.fields”,field);

component.set(‘v.fieldValue’,rowData[field]);

},

})

Client-side controller:

public class DynamicClass {

@AuraEnabled

public Boolean hasError;

@AuraEnabled

public String message;

@AuraEnabled

public List< String >  sdata;

@AuraEnabled

public List< sObject >  sObjectData;

@AuraEnabled

public static DynamicClass getRelatedSobjectName(String sObjectType){

DynamicClass controller = new DynamicClass();

controller.hasError = false;

try{

SObjectType objToken = Schema.getGlobalDescribe().get(sObjectType);

DescribeSObjectResult objDef = objToken.getDescribe();

Map< String, SObjectField > fields = objDef.fields.getMap();

List< String > fieldschema = new list< String >();

for(Schema.SObjectField sfield : fields.Values()) {

fieldschema.add(”+sfield);

}

if(fieldschema.Size() != null)

controller.sdata = fieldschema;

else

controller.sdata = null;

}catch(Exception e){

controller.hasError = true;

controller.message = ‘Exception:’+e.getMessage()+ ‘ ‘+e.getStackTraceString();

return controller;

}

return controller;

}

@AuraEnabled

public static DynamicClass getFields(String sObjectType, List< String > fieldsList, String Limits, String Types, String field){

DynamicClass controller = new DynamicClass();

controller.hasError = false;

try{

String Query;

//if the user gives the value in filter and leaves the Limits field empty

if(String.isEmpty(Limits) && !String.isEmpty(field) && String.isEmpty(Types)){

System.debug(‘if the user gives the value in filter and leaves the Limits field empty’);

Query = ‘SELECT ‘ +String.join(fieldsList, ‘,’);

Query += ‘ FROM ‘+sObjectType+ ‘ WHERE ‘+String.join(fieldsList, ‘!= null AND ‘)+’ != null AND ‘+field+ ‘ = null’;

}

//if the user gives the value in limits and leaves the filter field empty

else if(!String.isEmpty(Limits) && String.isEmpty(field) && String.isEmpty(Types)){

System.debug(‘if the user gives the value in limits and leaves the filter field empty’);

Query = ‘SELECT ‘ +String.join(fieldsList, ‘,’);

Query += ‘ FROM ‘+sObjectType+ ‘ WHERE ‘+String.join(fieldsList, ‘!= null AND ‘)+’ != null LIMIT ‘+Limits;

}

//if the user leaves both filter and Limits field as empty

else if(String.isEmpty(Limits) && String.isEmpty(field) && String.isEmpty(Types)){

System.debug(‘if the user leaves both filter and Limits as empty’);

Query = ‘SELECT ‘ +String.join(fieldsList, ‘,’);

Query += ‘ FROM ‘+sObjectType+ ‘ WHERE ‘+String.join(fieldsList, ‘!= null AND ‘)+’ != null’;

}

else if(String.isEmpty(Limits) && !String.isEmpty(field) && !String.isEmpty(Types)){

System.debug(‘if the user gives the value in filter and leaves the Limits field empty’);

Query = ‘SELECT ‘ +String.join(fieldsList, ‘,’);

Query += ‘ FROM ‘+sObjectType+ ‘ WHERE ‘+String.join(fieldsList, ‘!= null AND ‘)+’ != null AND ‘+field+ ‘ =: Types’;

}

//if the user gives the value in both filter and Limits

else{

System.debug(‘if the user gives the value in both filter and Limits’);

Query = ‘SELECT ‘ +String.join(fieldsList, ‘,’);

Query += ‘ FROM ‘+sObjectType+ ‘ WHERE ‘+String.join(fieldsList, ‘!= null AND ‘)+’ != null AND ‘+field+ ‘ =: Types LIMIT ‘+Limits;

}

System.debug(‘Query ===> ‘+Query);

List < sObject > returnList = new List < sObject > ();

List< sObject > ss = new List< sObject >();

ss = Database.query(Query);

for (sObject obj2: ss) {

returnList.add(obj2);

}

if(returnList.Size() != null)

controller.sObjectData = returnList;

else

controller.sdata = null;

}catch(Exception e){

controller.hasError = true;

controller.message = ‘Exception:’+e.getMessage()+ ‘ ‘+e.getStackTraceString();

return controller;

}

return controller;

}

@AuraEnabled

public static DynamicClass getStringField(String sObjectType){

DynamicClass controller = new DynamicClass();

controller.hasError = false;

try{

SObjectType objToken = Schema.getGlobalDescribe().get(sObjectType);

DescribeSObjectResult objDef = objToken.getDescribe();

Map< String, SObjectField > fields = objDef.fields.getMap();

List<String> fieldschema = new list<String>();

for(String sfield : fields.KeySet()) {

Schema.DescribeFieldResult describeResult = fields.get(sfield).getDescribe();

Schema.DisplayType s = objDef.fields.getMap().get(sfield).getDescribe().getType();

if(s == Schema.DisplayType.String){

fieldschema.add(”+sfield);

}

}

if(fieldschema.Size() != null)

controller.sdata = fieldschema;

else

controller.sdata = null;

}catch(Exception e){

controller.hasError = true;

controller.message = ‘Exception:’+e.getMessage()+ ‘ ‘+e.getStackTraceString();

return controller;

}

return controller;

}

}

Use Case:

Scenario:

  • if the business wants to see all the records from an object or some of the records that meet a specific criterion, this component can be used.

Step 1 : Place the component anywhere in the record Detail page.

Step 2: By clicking the button, we can see all the fields from that object. Then select the fields and click the Next button.Step 3:

Next, set up the criteria and # of records to limit in the results.

For Ex:

I want to see the records whose billing country is USA.Step 4:

 By clicking the Finish button, you can see a maximum of two records with billing country as USA.Step 5:

 If no records are found, we show message in a dialog box.References:

About MST

At MST Solutions our cornerstone is to adapt, engage and create solutions which guarantee the success of our clients. The talent of our team and experiences in varied business verticals gives us an advantage over other competitors.

Recent Articles

Work with us.

Our people aren’t just employees, they are key to the success of our business. We recognize the strengths of each individual and allow them time and resources to further develop those skills, crafting a culture of leaders who are passionate about where they are going within our organization.