Friday, February 22, 2019

How to show custom exception message in apex

This post explains how to show the custom exception in the apex
If you want to show any custom exceptions in the apex, create custom exception class and extends the standard Exception Class.
Example:
Apex Class
public class CustomExceptionController {
    public static void throwCustomException() {
        try {
            throw new customDemoException('This is Custom Exception Message');
        }
        catch(Exception ex) {
            System.debug('Custom Exception Message ===> '+ex.getMessage());
        }
    }
// custom exception class
public class customDemoException extends Exception {}
}
Run below code from the anonymous window.
CustomExceptionController.throwCustomException();

Result

Tuesday, February 19, 2019

Salesforce DX(SFDX) setup for non scratch org(Developer/Sandbox)

This post explains how to set up Salesforce DX(SFDX) for non-scratch org(Developer/Sandbox)

Step 1: install salesforce CLI and VS Code

1. Download and Install Salesforce CLI
2. Download vs code From this link and install.

Note: Once installed the Salesforce CLI you can verify using below command
sfdx --version
3. Install salesforcedx plugin using below command
sfdx plugins:install salesforcedx

Verify installed plugins using below command
sfdx plugins

Installing Salesforce Extensions in vs code
1. Open vs code install Salesforce extension pack

Step 2: Create a Project

Once complete the Step1, open the command palette
To open the command palette, press Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows or Linux).


Enter project Name and Select Folder
Once create the Project, configure the below files
1. sfdx-project.json
2. package.xml
sfdx-project.json
 if you are connecting to sandbox change the sfdcloginurl to test.salesforce.com
check below screenshot

package.xml
go to manifest folder ---> package.xml
add the components which data you want to retrieve in the package.xml
check below screenshot

Step 3: Authorize an Org

once complete the step2, open command palette then select SFDX: Authorize an Org

this command opens your default browser then login to your developer/sandbox org
once logged in to your org you may close your browser.

Step 4: Retrieve the source from org

once complete the step3, go to your package.xml, right click on the package.xml
select retrieve source in manifest from Org.
check screenshot
this command retrieves the source from your org, it is taken some time based on data in your Org.

Step 5: Deploy or retrieve the code from the server

Once you retrieve the source form your org, to open any file in the project folder press ctrl+p
it opens search palette.
check screenshot

if you want to save the code into your org, right click on that file, select SFDX: Deploy to org
if you want to refresh the file from server select SFDX: Retrieve the source from org
check below screenshot

That's it.
Let us know if you have any queries.

Monday, February 18, 2019

How to fire validation rule only in update operation?


This post explains how to fire the validation rule in the update operation.
Use NOT(ISNEW()) function it will stop the validation rule fire in the insert operation.
Example:
AND (
  NOT(ISNEW()),
  ISCHANGED(Phone)
)
above validation rule will fire only an update operation.


Saturday, February 16, 2019

Salesforce ContentDocumentLink Trigger

Topics Covered in this trigger
1.   Changing Filename based on Parent Record.
2.   Avoiding Duplicate Files insertion.
3.   Checking File Name Size.

Note: Salesforce not supporting to show custom error message while uploading files. maybe in future salesforce resolve this issue.
For more information about issue check below link
Custom Error message Not Showing When File Uploading

Example:
In this Example, I am checking only account object you can extend this functionality as per your requirement.

ContentDocumentLinkTrigger
trigger ContentDocumentLinkTrigger on ContentDocumentLink (after insert) {
    if(trigger.isAfter) {
        if(trigger.isInsert) {
            ContentDocumentLinkTriggerHandler.onAfterInsert(trigger.new);
        }
    }
}

ContentDocumentLinkTriggerHandler
public inherited sharing class ContentDocumentLinkTriggerHandler {
    
    public static void onAfterInsert(list<ContentDocumentLink> lstCntLinks) {
        String strObjPrefix;
        Set<Id> setCntDocIds = new set<Id>();
        set<Id> setAccIds = new set<Id>();
        map<Id, Account> mapAccs;
        
        for(ContentDocumentLink clIterator : lstCntLinks) {
            strObjPrefix = String.valueOf(clIterator.LinkedEntityId).substring(0, 3);
            if(strObjPrefix == Account.sObjectType.getDescribe().getKeyPrefix()) {
                setCntDocIds.add(clIterator.ContentDocumentId);
                setAccIds.add(clIterator.LinkedEntityId);
            }
        }
        
        if(!setCntDocIds.isEmpty()) {
            if(!setAccIds.isEmpty()) {
                mapAccs = new map<Id, Account>([SELECT Id, Name FROM Account WHERE Id IN :setAccIds]);
            }
        }
        
        // Get content document object for current set of files
        map<Id, ContentDocument> mapContentDocuments = new map<Id, ContentDocument>([SELECT Id, Title, FileExtension FROM ContentDocument WHERE Id IN :setCntDocIds]);
        
        // Retrieve all the existing attachments associated with the parent records
        map<Id, set<String>> mapParentIdFilenames = new map<Id, set<String>>();
        for (ContentDocumentLink cdlIterator : [SELECT Id, ContentDocumentId, LinkedEntityId, ContentDocument.Title, ContentDocument.FileExtension FROM ContentDocumentLink WHERE LinkedEntityId IN :setAccIds AND ContentDocumentId NOT IN :setCntDocIds]) {
            if (!mapParentIdFilenames.containsKey(cdlIterator.LinkedEntityId)) {
                mapParentIdFilenames.put(cdlIterator.LinkedEntityId, new set<String>());
            }
            mapParentIdFilenames.get(cdlIterator.LinkedEntityId).add(cdlIterator.ContentDocument.Title + (String.isBlank(cdlIterator.ContentDocument.FileExtension) ? '' : '.' + cdlIterator.ContentDocument.FileExtension));
        }
        
        Account objAcc;
        list<ContentDocument> lstCntDocsToUpdate = new list<ContentDocument>();
        
        for(ContentDocumentLink cdlIterator : lstCntLinks) {
            ContentDocument objCntDoc = mapContentDocuments.get(cdlIterator.ContentDocumentId);
            String strFilename = '';
            if(mapAccs.containsKey(cdlIterator.LinkedEntityId)) {
                objAcc = mapAccs.get(cdlIterator.LinkedEntityId);
                strFilename = objAcc.Name + '_Account_' + objCntDoc.Title + '.' + objCntDoc.FileExtension;
            }
            
            if(!String.isBlank(strFilename)) {
                set<String> setExistingFilenames = mapParentIdFilenames.get(cdlIterator.LinkedEntityId);
                if(objCntDoc.Title.length() > 40) {
                    cdlIterator.addError('Filename to long.');
                }
                else if (setExistingFilenames != null && setExistingFilenames.contains(strFilename + (String.isBlank(objCntDoc.FileExtension) ? '' : '.' + objCntDoc.FileExtension))) {
                    cdlIterator.addError('Attaching duplicate file, please choose different file.');
                }
                else {
                    objCntDoc.Title = strFilename;
                    lstCntDocsToUpdate.add(objCntDoc);
                }
            } 
        }
        if(!lstCntDocsToUpdate.isEmpty()) {
            update lstCntDocsToUpdate;
        }
        
    }
}

Result

Resources
ContentDocumentLink
ContentVersion
ContentDocument

Apex JSON Generator

This post explains how to generate JSON using Apex.

Example:
Apex Class
public class GenerateJSONDemo {
    
    public static string jsonGeneratorSample() {
        String strJson = '';
        
        for(Account accIterator : [SELECT Id, Name, Industry, Phone, Type From Account limit 5]) {
            try {
                // Create a JSONGenerator object
                JSONGenerator jsGen = JSON.createGenerator(true);
                // start object ({)
                jsGen.writeStartObject();
                jsGen.writeFieldName('Account');
                jsGen.writeStartObject();
                jsGen.writeStringField('Id', accIterator.Id);
                jsGen.writeStringField('Name', accIterator.Name);
                jsGen.writeStringField('Industry', accIterator.Industry);
                jsGen.writeStringField('Phone', accIterator.Phone);
                jsGen.writeStringField('Account Type', accIterator.Type);
                // end object (})
                jsGen.writeEndObject();
                jsGen.writeEndObject();
                strJson = jsGen.getAsString(); 
            }
            catch(Exception ex) {
                System.debug('Line number ====> '+ex.getLineNumber() + 'Exception Message =====> '+ex.getMessage());   
            }
        }
        if(!String.isBlank(strJson)) {
            return strJson;
        }
        else {
            return null;
        }
    }
}

Result
{
 "Account" : {
  "Id" : "0017F00001V3WVzQAN",
  "Name" : "Emporium",
  "Industry" : "Biotechnology",
  "Phone" : "4567890321",
  "Account Type" : "Installation Partner"
 }
 }

Resource:
JSONGenerator Class

Thursday, February 14, 2019

How to disable Lightning button after click the button

This post explains how to disable the lightning button in Lightning component.

Demo:

DisableButtonComponent
<aura:component controller="LightningRelatedExamples" implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" >
    <aura:attribute name="objAcc" type="Account"  default="{'sobjectType':'Account', 
                                                           'Name': '',
                                                           'Phone': '',
                                                           'Industry': '', 
                                                           'Type': ''}"/>
    <aura:attribute name="isHide" type="Boolean" default="false" />
    
    <!-- Notification library to show notifications-->
    <lightning:notificationsLibrary aura:id="notifLib"/>
    <div class="slds-theme_default">
        <div class="slds-form-element">
            <center>
                <label class="slds-form-element__label slds-text-heading_medium slds-m-bottom_medium" for="form-element-01">Create Account Form</label>
            </center>
            <div class="slds-form-element__control">
                <lightning:input name="name" type="text" required="true" label="Account Name" value="{!v.objAcc.Name}" />
                <lightning:input name="phone" type="text" label="Phone" value="{!v.objAcc.Phone}" />
                <lightning:input name="industry" type="text" label="Industry" value="{!v.objAcc.Industry}" />
                <lightning:input name="type" type="text" label="Account Type" value="{!v.objAcc.Type}" /> <br/>
                <center>
                    <lightning:button variant="brand" disabled="{!v.isHide}" label="{!v.isHide == true ? 'Account Created' : 'Create Account'}" onclick="{!c.saveAccount}" /> 
                </center>
            </div>
        </div>
    </div>
</aura:component>

DisableButtonComponentController.js
({
    saveAccount : function(component, event, helper) {
        var objAccount = component.get("v.objAcc");
        var action = component.get('c.insertAccount');
        action.setParams({
            objAcc:objAccount
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS") {
                component.find('notifLib').showToast({
                    "variant": "success",
                    "title": objAccount.Name,
                    "message": "The record has created successfully."
                });
                component.set('v.isHide', true);  
            }
        });
        $A.enqueueAction(action);
    }
})

Apex Controller
public inherited Sharing class LightningRelatedExamples {
    
    @AuraEnabled
    public static void insertAccount(Account objAcc) {
        if(objAcc != null) {
            try {
                insert objAcc;
            }
            catch(Exception ex) {
                 throw new AuraHandledException(ex.getMessage());
            }
        }
    }
}

Result

How to use Custom Labels in Lighting Component

This post explains how to use custom labels in Lightning Component.

Syntax

$Label.namespace.LabelName
if your org not having any names space use default namespace 'c'

Example:
Lightning Component
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="strLabelvalue" type="String" />
    <!-- System handler -->
    <aura:handler name="init" value="{!this}" action="{!c.getLabelValue}" />
    
    <center>
        <div class="slds-theme_default">
            <!-- Custom Label value from component -->
            <h2  class="slds-text-heading_medium slds-m-bottom_medium">Custom Label value from Lightning Component</h2>
            <p><b>{!$Label.c.SalesforceCodeCrack}</b></p><br/><br/>
            
            <!--Custom Label value from Controller -->
            <h2  class="slds-text-heading_medium slds-m-bottom_medium">Custom Label value from Controller</h2>
            <p><b>{!v.strLabelvalue}</b></p>
        </div>
    </center>
</aura:component>

Controller
({
 getLabelValue : function(component, event, helper) {
  var labelValue = $A.get("$Label.c.SalesforceCodeCrack");
        component.set('v.strLabelvalue', labelValue);
 },
})

Result:

Sunday, February 10, 2019

How to Query all fileds with SOQL in Apex

This post explains the how to query all fields with soql in apex.
By Default SOQL not Support for selecting All Fileds
SELECT * From sObject
check below generic class this class accepts the object name, based on object name it gives the  SOQL query in the form String.

Apex Class:
public inherited sharing class GenerateDynamicSOQLQuery {
    
    public static string getSOQLQuery(String strObjectName) {
        if(!String.isBlank(strObjectName)) {
            String strQuery = 'SELECT ';
            list<Schema.DescribeSObjectResult> objDiscribe = Schema.describeSObjects(new List<String>{strObjectName});
            map<String, Schema.SObjectField> objFileds = objDiscribe[0].fields.getMap();
            list<String> lstOfFieldNames = new list<String>(objFileds.keySet());
            strQuery = strQuery + String.join(lstOfFieldNames, ', ') + ' FROM ' +strObjectName;
            return strQuery;
        }
        else {
            return null;
        }
    }
}

Demo:
Open Execute Anonymous window execute below code
String strQuery = GenerateDynamicSOQLQuery.getSOQLQuery('Account');
strQuery += ' WHERE Industry = \'Banking\' LIMIT 1';
System.debug('Account Records ====>  '+Database.query(strQuery));
Result:

Happy Learning!!!

Saturday, February 9, 2019

How to Query all Object Names in org using SOQL

This post explains how to check all object names using SOQL.
Use below simple query to get all object names org.

SOQL Query
SELECT MasterLabel, PluralLabel, KeyPrefix, DeveloperName, QualifiedApiName, NamespacePrefix FROM EntityDefinition WHERE IsCustomSetting = false Order by MasterLabel

Result

Resource
EntityDefinition Tooling API 

Happy Learning!!

Saturday, February 2, 2019

How to Show Toast Notifications in Lightning Web Components(lwc)

This post explains how to show toast notifications in lightning web components(lwc).
To Show the toast notifications in Lighting Web Components, import ShowToastEvent from the lightning/platformShowToastEvent module.

Example:

LwcShowToastNotificationsDemo.html
<template>
    <lightning-card>
        <center>
            <div class="slds-m-top_medium slds-m-bottom_x-large">
                <h2 class="slds-text-heading_medium slds-m-bottom_medium">
                    Show Toast Notifications Demo
                </h2>

                <!-- Button group-->
                <lightning-button-group>
                    <lightning-button label="Show Success" onclick={handleSuccess}></lightning-button>
                    <lightning-button label="Show Error" onclick={handleError}></lightning-button>
                    <lightning-button label="Show Warning" onclick={handleWarning}></lightning-button>
                    <lightning-button label="Show Info" onclick={handleInfo}></lightning-button>
                </lightning-button-group>
            </div>
        </center>
    </lightning-card>
</template>

LwcShowToastNotificationsDemo.js
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

export default class LwcShowToastNotificationsDemo extends LightningElement {
    handleSuccess() {
        const showSuccess = new ShowToastEvent({
            title: 'Success!!',
            message: 'This is Success message.',
            variant: 'Success',
        });
        this.dispatchEvent(showSuccess);
    }
    
    handleError() {
        const showError = new ShowToastEvent({
            title: 'Error!!',
            message: 'This is Error message.',
            variant: 'error',
        });
        this.dispatchEvent(showError);
    }

    handleWarning() {
        const showWarning = new ShowToastEvent({
            title: 'Warning!!',
            message: 'This is Warning message.',
            variant: 'warning',
        });
        this.dispatchEvent(showWarning);
    }

    handleInfo() {
        const showInfo = new ShowToastEvent({
            title: 'Info!!',
            message: 'This is Info message.',
            variant: 'info',
        });
        this.dispatchEvent(showInfo);
    } 

}

LwcShowToastNotificationsDemo.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="lwcShowToastNotificationsDemo">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Output

Happy Learning!!!