Saturday, April 25, 2020

Comparable Interface in Salesforce

The Comparable interface adds sorting support for Lists that contain non-primitive types, that is, Lists of user-defined types.

To add List sorting support for your Apex class, you must implement the Comparable interface with its compareTo method in your class.

When a class implements the Comparable interface it has to implement a method called compareTo(). This method returns an integer value that is the result of the comparison.

compareTo(objectToCompareTo)
Returns an integer value that is the result of the comparison.

The implementation of this method returns the following values:

0 if this instance and objectToCompareTo are equal
> 0 if this instance is greater than objectToCompareTo
< 0 if this instance is less than objectToCompareTo

If this object instance and objectToCompareTo are incompatible, a System.TypeException is thrown.

Example:
global class Employee implements Comparable {

    public Long id;
    public String name;
    public String phone;
    
    // Constructor
    public Employee(Long i, String n, String p) {
        id = i;
        name = n;
        phone = p;
    }
    
    // Implement the compareTo() method
    global Integer compareTo(Object compareTo) {
        Employee compareToEmp = (Employee)compareTo;
        if (id == compareToEmp.id) return 0;
        if (id > compareToEmp.id) return 1;
        return -1;        
    }
}

Sort the List using compareTo(object) method.
List<Employee> empList = new List<Employee>();
empList.add(new Employee(101,'Joe Smith', '4155551212'));
empList.add(new Employee(101,'J. Smith', '4155551212'));
empList.add(new Employee(25,'Caragh Smith', '4155551000'));
empList.add(new Employee(105,'Mario Ruiz', '4155551099'));

// Sort using the custom compareTo() method
empList.sort();

// Write list contents to the debug log
for (Employee emp : empList){
 system.debug(emp);
}

Output


Format Dates and Time using Apex in Salesforce


This post explains how to format dates and times using apex.
The below table contains the formatting codes.

LetterDate or Time PieceExamples
GEraG = AD
yYearyy = 09, yyyy = 2009
MMonthMM = 08, MMM = Aug, MMMMM = August
wWeek in yearw = 35
WWeek in monthW = 3
DDay in yearD = 235
dDay in monthdd = 27
FDay of week in monthF = 2
EDay in weekE = Thu, EEEEE = Thursday
aAM/PMa = AM or PM
HHour in day (0-23)HH = 23
kHour in day (1-24)kk = 24
KHour in am/pm (0-11)KK=11
hHour in am/pm (1-12)hh = 12
mMinutes in hourmm = 30
sSecond in minutess = 55
SMillisecond in secondSSS = 888
zTime zonez = EDT, zzzzz = Eastern Daylight Time
ZTime zone offsetZ = -0400

Examples
DateTime dt = Datetime.now();
String strTimeInAMorPM = dt.format('MMMMM dd, yyyy hh:mm:ss a');
System.debug('time in am and pm ==> '+strTimeInAMorPM); 

String strTimeInWeek = dt.format('MMMMM dd, yyyy EEEE');
System.debug('strTimeInWeek ==> '+strTimeInWeek); 

String strTimezone = dt.format('MMMMM dd, yyyy z');
System.debug('strTimezone ==> '+strTimezone); 

Output

Friday, April 17, 2020

Handle Custom Validations in Lightning Web Components(lwc)

When we working with input values some times users enter the bad data, In this situation we need to validate the data and show the custom error message to the user to correct the data.

Use the setCustomValidity() and reportValidity() methods to validate and dsiplay custom error message.

Demo:
HTML Code
<template>
    <lightning-card title="Custom Validations In Lightning Web Components">
        <lightning-input class="nameCmp" label="Enter Name" type="string"></lightning-input>
        <lightning-input class="dateCmp" label="Enter Date" type="date"></lightning-input><br/><br/>
        <lightning-button class="slds-align_absolute-center" label="Search" variant="brand" onclick={searchTheData}></lightning-button>
    </lightning-card>
</template>

Javascript Code
import { LightningElement, track } from 'lwc';

export default class DemoApp extends LightningElement {

    searchTheData() {
        let searchCmp = this.template.querySelector(".nameCmp");
        let dateCmp = this.template.querySelector(".dateCmp");
        let searchvalue = searchCmp.value;
        let dtValue = dateCmp.value;
       
        if (!searchvalue) {
            searchCmp.setCustomValidity("Name value is required");
        } else {
            searchCmp.setCustomValidity(""); // clear previous value
        }
        searchCmp.reportValidity();

        if (!dtValue) {
            dateCmp.setCustomValidity("Date value is required");
        } else {
            dateCmp.setCustomValidity(""); // clear previous value
        }
        dateCmp.reportValidity();
    }
}

Output

Thursday, April 16, 2020

Custom data table with onload custom sorting in lightning web components(lwc)

This post explains the custom data table with onload custom sorting in lightning web components(lwc)

In some scenarios, we need to sort the data based on the particular field when table loading the data.

For Demo, I used the opportunity data and sort the data based on the amount field when table loading the data.

HTML Code
<template>
    <div if:true={oppData}>
        <table class="slds-table slds-cell-wrap">
            <thead>
                <tr class="slds-line-height_reset">
                    <th scope="col" data-id="Opportunity Name">
                        <b>Opportunity Name</b>
                    </th>

                    <th scope="col" data-id="Stage Name">
                        <b>Stage Name</b>
                    </th>
                    <th scope="col" data-id="Amount">
                        <b>Amount</b>
                    </th>
                </tr>
            </thead>
            <tbody>
                <template for:each={oppData} for:item="keyValue">
                    <tr key={keyValue.Id}>
                        <td>
                            <a href={oppURL} target="_blank" data-id={keyValue.Id} onclick={gotoOpp}>{keyValue.Name}</a>
                        </td>
                        <td>
                            {keyValue.StageName}
                        </td>
                        <td>
                            {keyValue.Amount}
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </div>
</template>

JS Controller
import {
    LightningElement,
    wire
} from 'lwc';
import opps from "@salesforce/apex/GenericController.returnOpps";

export default class OnloadSorting extends LightningElement {
    oppData = [];
    oppURL;

    @wire(opps)
    opp({
        error,
        data
    }) {
        if (data) {
            console.log('data ===> ' + JSON.stringify(data));
            this.oppData = JSON.parse(JSON.stringify(data)).sort((a, b) => {

                Object.keys(a).map((key) => {
                    if (key == 'Amount') {
                        a = a[key];
                    }
                });

                Object.keys(b).map((key) => {
                    if (key == 'Amount') {
                        b = b[key];
                    }
                });

                return -1 * ((a > b) - (b > a));

            });
        } else if (error) {
            console.log(error);
        }
    }

    gotoOpp(event) {
        this.oppURL = window.location.origin + "/" + event.currentTarget.dataset.id;
    }
}

Apex Class
public inherited sharing class GenericController {
    @AuraEnabled(Cacheable=true)
    public static list<Opportunity> returnOpps(){
        return [SELECT Id, Name, StageName, Amount FROM Opportunity WHERE amount != null limit 10];
    }
}

Output

Saturday, April 11, 2020

How to enable user based manual sharing in Salesforce

Path:

Setup  =>  Sharing Settings => click on Edit.


Go to other settings and enable manual user record sharing.


Once you enable the sharing, go to the object page layout and add the manual sharing button to the layout.

That's it.


Monday, April 6, 2020

Salesforce Objects That Don’t Support DML Operations

Below Objects are don't support DML operations in salesforce.

  • AccountTerritoryAssignmentRule
  • AccountTerritoryAssignmentRuleItem
  • ApexComponent
  • ApexPage
  • BusinessHours
  • BusinessProcess
  • CategoryNode
  • CurrencyType
  • DatedConversionRate
  • NetworkMember (allows update only)
  • ProcessInstance
  • Profile
  • RecordType
  • SelfServiceUser
  • StaticResource
  • Territory2
  • UserAccountTeamMember
  • UserPreference
  • UserTerritory
  • WebLink

Saturday, April 4, 2020

Custom Sorting of Data Table on Client Side In Salesforce Lightning Web Components(lwc)

This post explains how to sort data in the custom data table in the lightning web component(lwc)

For the demo, using the account data when you click on the column header the data automatically sorted.

For sorting, I used the sort method.

Apex Class
public inherited sharing class GenericController {
    @AuraEnabled(Cacheable=true)
    public static list<Account> returnAccs(){
        return [SELECT Id, Name, Industry, Type,Phone, Rating, AccountNumber FROM Account];
    }
}


HTML Code
<template>
    <lightning-card title="Custom Sorting on Datatable in Lightning Web Components">
        <table class="slds-table slds-table--bordered slds-table--cell-buffer">
            <thead>
                <tr class="slds-text-title--caps">
                    <th data-id="Name" onclick={sortName}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Name">Name</span>
                            <div if:true={isNameSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="AccountNumber" onclick={sortAccNumber}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Type">Account Number</span>
                            <div if:true={isAccNumSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="Industry" onclick={sortIndustry}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Industry">Industry</span>
                            <div if:true={isIndustrySort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="Type" onclick={sortType}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Type">Type</span>
                            <div if:true={isTypeSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="Phone" onclick={sortPhone}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Phone">Phone</span>
                            <div if:true={isPhoneSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
                <template for:each={accounts} for:item="acc">
                    <tr key={acc.Id}>
                        <td>
                            <a href={accURL} 
                               target="_blank" 
                               data-id={acc.Id} 
                               onclick={gotoAccount}>{acc.Name}</a>
                        </td>
                        <td>
                            {acc.AccountNumber}
                        </td>
                        <td>
                            {acc.Industry}
                        </td>
                        <td>
                            {acc.Type}
                        </td>
                        <td>
                            <lightning-formatted-phone value={acc.Phone}></lightning-formatted-phone>
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </lightning-card>
</template>

Javascript Code
import {LightningElement,wire} from 'lwc';
import accs from '@salesforce/apex/GenericController.returnAccs';

export default class CustomSorting extends LightningElement {

    accounts = [];
    accURL = "";
    isAsc = false;
    isDsc = false;
    isNameSort = false;
    isPhoneSort = false;
    isIndustrySort = false;
    isTypeSort = false;
    isAccNumSort = false;
    error;

    sortedDirection = 'asc';
    sortedColumn;

    @wire(accs)
    acc({error, data}) {
        if (data) {
            this.accounts = data;
        } else if (error) {
            this.error = error;
            console.log('error ===> ' + JSON.stringify(error));
        }
    }

    gotoAccount(event) {
        this.accURL = window.location.origin + "/" + event.currentTarget.dataset.id;
    }

    sortName(event) {
        this.isNameSort = true;
        this.isPhoneSort = false;
        this.isIndustrySort = false;
        this.isTypeSort = false;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortAccNumber(event) {
        this.isNameSort = false;
        this.isPhoneSort = false;
        this.isIndustrySort = false;
        this.isTypeSort = false;
        this.isAccNumSort = true;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortIndustry(event) {
        this.isNameSort = false;
        this.isPhoneSort = false;
        this.isIndustrySort = true;
        this.isTypeSort = false;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortPhone(event) {
        this.isNameSort = false;
        this.isPhoneSort = true;
        this.isIndustrySort = false;
        this.isTypeSort = false;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortType(event) {
        this.isNameSort = false;
        this.isPhoneSort = false;
        this.isIndustrySort = false;
        this.isTypeSort = true;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortData(sortColumnName) {
        // check previous column and direction
        if (this.sortedColumn === sortColumnName) {
            this.sortedDirection = this.sortedDirection === 'asc' ? 'desc' : 'asc';
        } 
        else {
            this.sortedDirection = 'asc';
        }

        // check arrow direction
        if (this.sortedDirection === 'asc') {
            this.isAsc = true;
            this.isDsc = false;
        } 
        else {
            this.isAsc = false;
            this.isDsc = true;
        }

        // check reverse direction
        let isReverse = this.sortedDirection === 'asc' ? 1 : -1;

        this.sortedColumn = sortColumnName;

        // sort the data
        this.accounts = JSON.parse(JSON.stringify(this.accounts)).sort((a, b) => {
            a = a[sortColumnName] ? a[sortColumnName].toLowerCase() : ''; // Handle null values
            b = b[sortColumnName] ? b[sortColumnName].toLowerCase() : '';

            return a > b ? 1 * isReverse : -1 * isReverse;
        });;
    }
}

Configuration File
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>  
        <target>lightning__HomePage</target>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>

Output

Thursday, April 2, 2020

How to query custom buttons/links info using SOQL in salesforce

Salesforce internally stores the all custom buttons and custom links and URL buttons info in Weblink object.

SOQL

Select Id, Name, LinkType, PageOrSobjectType From WebLink where NamespacePrefix = ''

you can filter Link type
URL
sControl
javascript
page
flow—Reserved for future use.

Output