Thursday, 15 April 2021
Mass\Bulk Operations in Salesforce using Batch Apex
Thursday, 8 April 2021
Salesforce Lightning TreeGrid with pagination
INTRODUCTION/SCENARIO
CHALLENGE
APPROACH / SOLUTION
public class treeGridController { @AuraEnabled public static List <Account> getAccountList() { return [Select Id, Name, (SELECT Name, Phone, Email FROM Contacts) From Account Where Id IN (Select AccountId From Contact) ORDER BY Name ASC]; } }
<aura:component controller="treeGridController" implements="flexipage:availableForAllPageTypes" > <aura:attribute name="resultData" type="Object" access="private"/> <aura:attribute name="gridColumns" type="List" /> <aura:attribute name="gridData" type="Object" /> <aura:attribute name="gridExpandedRows" type="Object" /> <aura:attribute name="PageNumber" type="Integer" /> <aura:attribute name="TotalPages" type="Integer"/> <aura:attribute name="currentPage" type="Integer" default="0" /> <aura:attribute name="limit" type="Integer" default="5" /> <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <div class="slds-page-header" role="banner"> <ui:inputSelect aura:id="pageSize" label="Display Records Per Page: " change="{!c.onSelectChange}"> <ui:inputSelectOption label="5" text="5" value="true"/> <ui:inputSelectOption label="10" text="10"/> <ui:inputSelectOption label="50" text="50"/> </ui:inputSelect> </div> <lightning:treeGrid aura:id="accTree" columns="{!v.gridColumns}" data="{!v.gridData}" expandedRows="{!v.gridExpandedRows}" keyField="Id" hideCheckboxColumn = "true" /> <div class="slds-clearfix"> <div class="slds-page-header" role="banner"> <div class="slds-float_right"> <lightning:button disabled="{!v.PageNumber == 1}" variant="brand" aura:id="prevPage" label="Prev" onclick="{!c.handlePrev}" /> <lightning:button disabled="{!v.PageNumber == v.TotalPages}" aura:id="nextPage" variant="brand" label="Next" onclick="{!c.handleNext}"/> </div> <p class="slds-page-header__title">Page {!v.PageNumber} of {!v.TotalPages}</p> </div> </div> </aura:component>
({
doInit : function(component, event, helper) {
var columns = [
{
type: 'url',
fieldName: 'AccountURL',
label: 'Account Name',
typeAttributes: {
label: { fieldName: 'accountName' }
}
},
{
type: 'text',
fieldName: 'Name',
label: 'Contact Name'
},
{
type: 'phone',
fieldName: 'Phone',
label: 'Phone Number'
},
{
type: 'email',
fieldName: 'Email',
label: 'Email'
}
];
component.set('v.gridColumns', columns);
var action = component.get("c.getAccountList");
action.setCallback(this, function(response){
var state = response.getState();
if (state === "SUCCESS" ) {
var resultData = response.getReturnValue();
component.set('v.resultData', resultData);
helper.bindTableData(component, event);
}
});
$A.enqueueAction(action);
},
handleNext : function(component, event, helper){
component.set('v.currentPage',component.get('v.currentPage')+1);
helper.buildTable(component, event);
},
handlePrev : function(component, event, helper){
component.set('v.currentPage',component.get('v.currentPage')-1);
helper.buildTable(component, event);
},
onSelectChange : function(component, event, helper){
component.set('v.currentPage',0);
var pageSize = component.find('pageSize').get('v.value');
component.set('v.limit',pageSize);
helper.buildTable(component, event);
}
})
({
bindTableData : function(component, event) {
var resultData = component.get('v.resultData');
for (var i=0; i<resultData.length; i++ ) {
resultData[i].accountName = resultData[i]['Name'];
delete resultData[i]['Name'];
resultData[i]._children = resultData[i]['Contacts'];
delete resultData[i].Contacts;
resultData[i].AccountURL = '/'+resultData[i].Id;
}
component.set('v.resultData',resultData);
this.buildTable(component, event);
},
buildTable : function(component, event){
var resultData = component.get('v.resultData');
var limit = component.get('v.limit');
var currentPage = component.get('v.currentPage');
var totalPage = Math.ceil(resultData.length / limit);
var startIndex = currentPage * limit;
var row = [];
var expandedRows = [];
for (var i = startIndex; i < parseInt(startIndex)+parseInt(limit); i++) {
if(resultData[i]){
expandedRows.push(resultData[i].Id);
row.push(resultData[i]);
}
}
component.set('v.gridData', row);
component.set('v.PageNumber',currentPage+1);
component.set('v.TotalPages',totalPage);
component.set('v.gridExpandedRows', expandedRows);
}
})
OUTPUT:
Thursday, 18 March 2021
Display Picklist values dynamically in lightning component
Challenge:
Mass Edit feature was implemented using the Custom Lightning component. And, there is no out-of-the-box (OOTB) feature available to display selected pick-list values in the in lightning component, while bulk edit is being performed.
To overcome this limitation, we have created an Apex class that contains the mechanism to retrieve the list of Industry (pick-list) field values from the Account object.
<aura:iteration items="{!v.selectedlst}" var="ac" > <c:DynamicPickController selectedOptions = '{!v.selectedlst}' Name = '{!ac.lstTelLineAccLocUserobject2.Name}' Industry = '{!ac.lstTelLineAccLocUserobject2.Industry}' pickvalues = '{!v.pickvalues}' /> </aura:iteration>
DynamicPickController.Js
doInit : function(component, event, helper) { var IndustryPick = []; for(var i = 0 ; i < component.get("v.pickvalues").length ; i++) { if(component.get("v.pickvalues")[i] == component.get("v.Industry")) { IndustryPick.push({"label":component.get("v.pickvalues")[i], "value":component.get("v.pickvalues")[i], "selected":true}) } else { IndustryPick.push({"label":component.get("v.pickvalues")[i], "value":component.get("v.pickvalues")[i]}) } } component.set("v.IndustryPick", IndustryPick); }
DynamicPickController.Cmp
<aura:attribute name="pickvalues" type="list"/><aura:handler name="init" value="{!this}" action="{!c.doInit}" /><lightning:select name="Industry" label="Select a Industry:" aura:id="Industry" value="{!v.Industry}">
<aura:iteration items="{!v.IndustryPick}" var="option"> <option text="{!option.label}" value="{!option.label}" selected="{!option.selected}"/> </aura:iteration> </lightning:select>
Output:
Thursday, 11 March 2021
Hyperlink a Record in lightning:datatable
Requirement:
While working on one of the user stories of healthcare sector project for a client based out of Atlanta, GA, USA, there was a need of displaying a list of Contacts in lightning:datatable having 2 columns with hyperlinks. One is contact name and other is account name. And clicking on it, it should redirect to contact record and account record respectively.Challenge:
The challenging part was, there is no standard functionality available in the lightning:datatable for a hyperlink field to redirect to record detail page.Solution:
To overcome this limitation, we'd to make changes in column format for a Contact name and Account name fields with type:'url' and also need to add typeAttributes as display below.
{ label: 'Name', fieldName: 'contacturl', type: 'url', typeAttributes: { label: { fieldName: 'Name' }, target: '_blank' } }, { label: 'Account Name', fieldName: 'accounturl', type: 'url', typeAttributes: { label: { fieldName: 'AccountName' }, target: '_blank' } }
ContactControllerpublic class ContactController { @AuraEnabled public static List < Contact > fetchContacts() { return [ SELECT Id, Name, Account.Id, Account.Name,Phone,Department,LeadSource FROM Contact]; } }
<aura:component implements="force:appHostable" controller="ContactController"> <aura:attribute type="Contact[]" name="conList"/> <aura:attribute name="columns" type="List"/> <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <lightning:datatable data="{!v.conList}" columns="{!v.columns}" keyField="Id" hideCheckboxColumn="true"/> </aura:component>
({
doInit : function( component, event, helper ) {
component.set('v.columns', [
{ label: 'Name', fieldName: 'contacturl', type: 'url',
typeAttributes: { label: { fieldName: 'Name' }, target: '_blank' }},
{label: 'Department',fieldName: 'Department', type: 'Text' },
{label: 'Lead Source',fieldName: 'LeadSource', type: 'Phone' },
{label: 'Phone',fieldName: 'Phone', type: 'Phone' },
{ label: 'Account Name', fieldName: 'accounturl', type: 'url',
typeAttributes: { label: { fieldName: 'AccountName' }, target: '_blank' } }
]);
//getting contact records
var action = component.get( "c.fetchContacts" );
action.setCallback(this, function( response ) {
var state = response.getState();
if ( state === "SUCCESS" ) {
var records = response.getReturnValue();
//setting value for url
records.forEach( function( record ) {
record.AccountName = record.Account.Name;
record.accounturl = '/' + record.Account.Id;
record.Name = record.Name;
record.contacturl = '/' + record.Id;
});
component.set( "v.conList", records );
}
});
$A.enqueueAction( action );
}
})
<aura:application access="GLOBAL" extends="force:slds"> <c:HyperLinkDatatable/> </aura:application>
Friday, 13 November 2020
Salesforce Releases its Top Features Of Winter '21
Salesforce Release Winter'21
Now we can plan when to send a list email. Choose the right time and date to ensure the best time to receive emails. We determine which emails we would like to send — and on which days. By scheduling, we can build emails ahead of time and schedule when they're out. By planning all of our email choices ahead, we will make our marketing activities even more efficient. For example, schedule a list email to arrive on a working day. Previously, scheduling was only available for individual emails, not for list emails.
When it comes to growth, organizational performance is the ruler. If users experience sluggish performance or long page loading times when using Lightning Experience, they no longer need to worry. Find suggestions for a better performance of the record page based on an analysis of the page right inside the Lightning App Builder. Performance Analysis in the App Builder tests the fields, instances of the Relevant Lists component, and the metadata of the record page. By clicking the Analyze button, get an analysis of the page with suggestions for improving the page performance.
Display survey pages that are focused on your data
With each update, Salesforce Surveys seem to be getting more and more strong. Now, we can use our data in Salesforce org to decide which survey page the user will see next. Users will move to the relevant page on the basis of the answer. We can use the variables to specify the conditions in Page branching logic. Now the user will experience a new journey.
Choose the Position of your utility bar
The utility bar gives easy access to common productivity tools, such as Notes and Recent items. Now, we can choose the position of our Salesforce org utility bar. Customize where our utility bar appears. We may move the utility bar to the bottom right or to the bottom left of the screen.
Trigger a flow before the record is deleted
Previously, we always need a trigger to add any validation or functionality before a record is deleted. We don't need to write an Apex code anymore. We can now use a flow to run before the record is deleted. This auto launched flow will execute in the background and update relevant records when a record is deleted.
Use Safe Navigation Operator to Remove NullPointerException
Winter'21 is bringing us a new safe navigation operator (?.). We can use the safe navigation operator (?.) to remove the consecutive condition that checks for null references. We may prevent NullPointerException with the aid of this new operator. This operator handles expressions that try to run on a null value and returns null instead of raising a NullPointerException. The right-hand side evaluates only if the left-hand side is not evaluated to null. In the variable as well as in the function, we can use a safe navigation operator.
This expression will first test x and return null if x is null. Otherwise, the return value will be x.y
// code checking for nulls x?.y // test to: x == null? Null : x.y This example demonstrates a SOQL query using a safe navigation operator. ContactRec = [SELECT FirstName FROM Contact WHERE Id = :contactId]; if (ContactRec.size() == 0) // Contact was deleted { return null; } return ContactRec[0].FirstName; //New Code return [SELECT FirstName FROM Contact WHERE Id = : contactId]?.FirstName;
Enhance Apex Testing with New SObject Error Methods
New Release gives us new SObject Error methods that minimize our efforts. Previously, we needed to perform DML operations to check the result for errors. Now we can monitor errors with the new SObject.hasErrors() method and SObject.getErrors() method without running a DML operation. Use SObject.addError() method to add errors to the specific fields. The hasErrors() method checks if an instance of SObject contains errors. We can get a list of errors for a specific instance of SObject using the getErrors() method.
//Base code sample for use with addError, getErrors Contact con = new Contact(); String message = 'New error in SObject'; con.addError('FirstName', message); //New overload that dynamically embraces the field at runtime List<Database.Error> errors = con.getErrors(); System.debug( errors.size()); //print 1 in debug Database.Error error = errors.get(0); System.debug(error.getStatusCode()); //print FIELD_CUSTOM_VALIDATION_EXCEPTION in debug String[] fields = error.getFields(); System.debug(fields); // print FirstName in debug System.debug(fields.size()); // print 1 in debug
If you have any questions you can reach out our Salesforce Consulting team here.
Tuesday, 15 September 2020
[SOLVED]: Issue on getting Parent record-Id (whoid) while retrieving Task details generated through Email-To-Task
EmailTask Class
global class EmailTask { @future public static void getUpdate(set<Id> taskIds){ //store WhoId and Task Record to the Map Map<Id,Task> taskWhoMap = new map<Id,Task>(); List<Task> TaskList = [Select Id,whoId,ActivityDate from task where Id IN :taskIds AND WhoId!= null]; if(TaskList.size()>0){ for(Task t : TaskList){ taskWhoMap.put(t.WhoId,t); } } if(taskwhomap.keySet().size()>0){ List<Contact> contactList =[select Id, Last_Sales_Activity_Date__c from Contact where Id =: taskwhomap.keySet()]; if(contactList.size()>0){ for(Contact c : contactList) { if(taskwhomap.containsKey(c.Id)){ // store due date of task in Contact date field c.Last_Sales_Activity_Date__c= taskwhomap.get(c.Id).ActivityDate; } } // updating contact update contactList; } } List<Lead> leadList =[select Id, Last_Sales_Activity_Date__c from Lead where
Id =: taskwhomap.keySet()]; if(leadList.size()>0){ for(Lead l : leadList) { if(taskwhomap.containsKey(l.Id)){ // store due date of task in Lead date field l.Last_Sales_Activity_Date__c= taskwhomap.get(l.Id).ActivityDate; } } // updating Lead update leadList; } } }
trigger Email on Task (After insert,After update) { if(trigger.Isafter){ if(trigger.Isinsert || trigger.Isupdate){ set<Id> TaskId = new set<Id>(); for(Task t : trigger.new){ TaskId.add(t.Id); } EmailTask.getUpdate(taskIds); } } }










