August 30, 2021

How to sign up for Salesforce Winter '22 Pre-Release org?


2. Enter all the information. Click Start Trial to sign up.
 

August 28, 2021

Quick Actions not showing even after adding it to the page layout in Salesforce

1. If it is a record creation specific Quick Action, 
a. Make sure the user have edit access to the record.
b. Make sure the user's profile have Read and Edit Field Level Permission to Parent field. 
c. Check the whether the user's profile have access to the Record Type selected.
 
2.  If Quick Actions on Cases and Work Orders are not visible, then kindly check https://www.infallibletechie.com/2018/12/quick-actions-on-cases-and-work-orders.html.

3. Check the page layout assignment and confirm whether it is added to the assigned page layout.

4. If Dynamic Actions are use, then edit the Lightning Record Page, check the Highlight Panel Component and confirm whether the quick action is hidden with condition.

August 26, 2021

Salesforce User Login IP

 1. Create a Report with Users as the Report Type.


2. Add Source IP Address to the Report.


Dynamically Change Language for Salesforce Embedded Service Chat

Apex Class:
public class EmbeddedChatController {

    public String selectedOption { get; set; }
    
    public EmbeddedChatController() {
    
        selectedOption = ApexPages.currentPage().getParameters().containsKey( 'language' ) ? ApexPages.currentPage().getParameters().get( 'language' ) : 'da';
        
    }
    
    public PageReference changeLanguage() {
    
        system.debug( 'Changed Language is ' + selectedOption );
        PageReference pg = new PageReference( '/apex/EmbeddedChat' );
        pg.getParameters().put( 'language', selectedOption );
        pg.setRedirect(true);
        return pg;
    
    }

}

Visualforce Page:


Output:


August 25, 2021

Custom message Salesforce Chat Window

Sample code:
<apex:page showHeader="false">
    <style>
        #liveAgentClientChat.liveAgentStateWaiting {
            font-weight: bold;
            font-size: 30px;
        }
        body { overflow: hidden; width: 100%; height: 100%; padding: 0; margin: 0 }
        #waitingMessage { height: 100%; width: 100%; vertical-align: middle; text-align: center;
        display: none; }
        #liveAgentClientChat.liveAgentStateWaiting #waitingMessage { display: table; }
        #liveAgentSaveButton, #liveAgentEndButton { z-index: 2; }
        .liveAgentChatInput {
            height: 25px;
            border-width: 1px;
            border-style: solid;
            border-color: #000;
            padding: 2px 0 2px 4px;
            background: #fff;
            display: block;
            width: 99%;
        }
        .liveAgentSendButton {
            display: block;
            width: 60px;
            height: 31px;
            padding: 0 0 3px;
            position: absolute;
            top: 0;
            right: -67px;
        }
        #liveAgentChatLog {
            width: auto;
            height: auto;
            top: 0px;
            position: absolute;
            overflow-y: auto;
            left: 0;
            right: 0;
            bottom: 0;
        }
    </style>
    <div style="top: 0; left: 0; right: 0; bottom: 0; position: absolute;">
        <liveAgent:clientChat>
            <liveAgent:clientChatSaveButton />
            <liveAgent:clientChatEndButton />
            <div style="top: 25px; left: 5px; right: 5px; bottom: 5px; position: absolute; z-index:0;">
                <liveAgent:clientChatAlertMessage />
                <liveAgent:clientChatStatusMessage />
                <table id="waitingMessage" cellpadding="0" cellspacing="0">
                    <tr>
                        <td>Please wait!!! We are connecting you to an available agent to address your issue.</td>
                    </tr>
                </table>
                <div style="top: 0; right: 0; bottom: 41px; left: 0; padding: 0; position: absolute;word-wrap: break-word; z-index: 0;">
                    <liveAgent:clientChatLog />
                </div>
                <div style="position: absolute; height: auto; right: 0; bottom: 0; left: 0; margin-right:67px;">
                    <liveagent:clientChatInput /><liveAgent:clientChatSendButton />
                </div>
            </div>
        </liveAgent:clientChat>
    </div>
</apex:page>
 
Chat button Configuration:
 

Output:
 

How to invoke Embedded Service Chat on click of a button in Salesforce?

embedded_svc.bootstrapEmbeddedService() can be used. Check the following article for additional information.  
 
Sample Code:
<apex:commandButton value="Start Chat" onclick="embedded_svc.bootstrapEmbeddedService();" reRender="chatDetails"/> 

Salesforce Chat Transfer

Agents can click Transfer icon to transfer the Chat.
 


August 24, 2021

How to debug JavaScript Custom Button in Salesforce?

Sample JavaScript Custom Button 
 

 Button on the Record Page:
 

Output:
 


August 21, 2021

How to read data from csv and load it into object using LWC in Salesforce?

Sample CSV File:


Sample code:

Apex:
public with sharing class FileUploadController {
    
    @AuraEnabled
    public static String loadData( Id contentDocumentId ) {

        String strMessage;
        List < Contact > contactList = new List < Contact >();

        if ( contentDocumentId != null ) {
            
            ContentVersion contentVersionObj = [ SELECT Id, VersionData FROM ContentVersion WHERE ContentDocumentId =:contentDocumentId ];
            List < String > records = contentVersionObj.VersionData.toString().split( '\n' );
            //Removing the Header
            records.remove( 0 );

            for ( String record : records ) {

                if ( record != null ) {

                    Contact objContact = new Contact();
                    List < String > row = record.split( ',' );
                    objContact.FirstName = row[ 0 ];
                    objContact.LastName = row[ 1 ];
                    objContact.Email = row[ 2 ];
                    contactList.add( objContact );

                }

            }

            try {    

                if ( contactList.size() > 0 ) {

                    Database.DeleteResult deleteResult = Database.delete( contentDocumentId, true );
                    insert contactList;
                    strMessage = 'Records loaded successfully';

                }

            }
            catch ( Exception e ) {

                strMessage = 'Some error occured. Please reach out to your System Admin';
                system.debug( e.getMessage() );

            } 
        }

        return strMessage;

    }

}

HTML:
<template>
    <template if:true={isLoaded}>
        <lightning-spinner 
            alternative-text="Loading" 
            size="large">
        </lightning-spinner>
    </template>
    <lightning-card variant="Narrow" icon-name="standard:file" title="File Upload">
        <p class="slds-var-p-horizontal_small">
            <lightning-file-upload 
                accept={acceptedFormats} 
                label="Attach CSV File" 
                multiple="multiple" 
                onuploadfinished={uploadFileHandler}>
            </lightning-file-upload>
        </p>
    </lightning-card>
</template>

JavaScript:
import { LightningElement } from 'lwc';
import {ShowToastEvent} from 'lightning/platformShowToastEvent';
import loadData from '@salesforce/apex/FileUploadController.loadData';

export default class FileUpload extends LightningElement {

    error;
    isLoaded = false;

    get acceptedFormats() {
        return ['.csv'];
    }
    
    uploadFileHandler( event ) {
        
        this.isLoaded = true;
        const uploadedFiles = event.detail.files;

        loadData( { contentDocumentId : uploadedFiles[0].documentId } )
        .then( result => {

            this.isLoaded = false;
            window.console.log('result ===> '+result);
            this.strMessage = result;
            this.dispatchEvent(
                new ShowToastEvent( {
                    title: 'Success',
                    message: result,
                    variant: result.includes("success") ? 'success' : 'error',
                    mode: 'sticky'
                } ),
            );

        })
        .catch( error => {

            this.isLoaded = false;
            this.error = error;
            this.dispatchEvent(
                new ShowToastEvent( {
                    title: 'Error!!',
                    message: JSON.stringify( error ),
                    variant: 'error',
                    mode: 'sticky'
                } ),
            );     

        } )

    }
}

meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
     <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>

Output:








August 20, 2021

How to get label/name of the object using API Name in Salesforce?

Sample code:
DescribeSObjectResult objDescribe = SObjectType.Employee__c;
system.debug( 'Label is ' + objDescribe.getLabel() );

Output:
 

August 19, 2021

How to refresh cache when using Lightning Navigation in Lightning Web Component in Salesforce?

Please check the following article.
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_navigate_basic

[NavigationMixin.GenerateUrl](pageReference)
A component calls this[NavigationMixin.GenerateUrl] to get a promise that resolves to the resulting URL. The component can use the URL in the href attribute of an anchor. It can also use the URL to open a new window using the window.open(url) browser API.


Sample Code:
HTML:

<template>    
    <lightning-button variant="brand" label="Cancel" onclick={cancel}></lightning-button>
</template>

JavaScript:
import { LightningElement, api } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';

export default class NewEmployeeChild extends  NavigationMixin( LightningElement ) {

    @api accountId;
    accountURL;
    url;

    connectedCallback() {
        
        this.accountURL = {
            type: 'standard__recordPage',
            attributes: {
                recordId: this.accountId,
                objectApiName: 'Account',
                actionName: 'view'
            }
        };
        this[ NavigationMixin.GenerateUrl ]( this.accountURL )
            .then( url => this.url = url );

    }

    cancel() {

        console.log( 'URL is ' + this.url );
        window.open( this.url, '_self' );

    }

}

August 18, 2021

System.LimitException: Too many queueable jobs added to the queue

Reference Article - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_queueing_jobs.htm

Limits.getQueueableJobs(): getQueueableJobs() Returns the number of queueable jobs that have been added to the queue per transaction. A queueable job corresponds to a class that implements the Queueable interface.
 
You can add up to 50 jobs to the queue with System.enqueueJob in a single transaction. 

When chaining jobs with System.enqueueJob, you can add only one job from an executing job. Only one child job can exist for each parent queueable job. Starting multiple child jobs from the same queueable job isn’t supported.

System.LimitException: Too many queueable jobs added to the queue: 2
You can only create one queueable job within a batch execution.

Sample code to reproduce:
Queueable Interface:
public class SampleQueueable implements Queueable {

    public void execute(QueueableContext context) {
    
        system.debug( 'Inside Queueable Interface' );
        
    }
    
}
 
Batch Apex:
global class SampleBatch implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start( Database.BatchableContext BC ) {
    
        String strSOQL = 'SELECT Id FROM Account LIMIT 2';
        return Database.getQueryLocator( strSOQL );
        
    }
    
    global void execute( Database.BatchableContext BC, List< Account > listAccounts ) {
    
        for ( Account acc : listAccounts ) {
            System.enqueueJob( new SampleQueueable() );
        }
        
    }   
    
    global void finish( Database.BatchableContext BC ) {
    }
    
}

Code to execute to reproduce the issue:
Database.executeBatch( new SampleBatch() );

August 17, 2021

New Button Override in Salesforce Lightning Related List

Sample code:
Component:

<aura:component implements="lightning:actionOverride, lightning:isUrlAddressable">
    <aura:attribute name="recordId" type="Id"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    Record Id is {!v.recordId}.
</aura:component>

Controller:
({
    
    doInit : function( component, event, helper ) {
        
        let pageRef = component.get("v.pageReference");
        console.log( 'Page Ref is ' + JSON.stringify( pageRef ) );
        let state = pageRef.state; // state holds any query params
        let base64Context = state.inContextOfRef;
        if ( base64Context.startsWith("1\.") ) {
            base64Context = base64Context.substring( 2 );
        }
        let addressableContext = JSON.parse( window.atob( base64Context ) );
        component.set( "v.recordId", addressableContext.attributes.recordId );
        
    }
    
})


New Button Override:
 

Output:



Pass params to Salesforce Inbount REST API

Sample Code:
@RestResource(urlMapping='/InboundRESTAPI/*')
global with sharing class InboundRESTAPIController {

    @HttpGet
    global static Account fetchAccount() {
        
        RestRequest req = RestContext.request;
        Map < String, String > params = req.params;
        Id accId = params.containsKey( 'accId' ) ? params.get( 'accId' ) : null;
        return [ SELECT Id, Name, Industry, AccountNumber FROM Account WHERE Id =: accId ];
    
    }
 
}


Output:



August 16, 2021

Salesforce Einstein Bot without Pre-Chat

Disable "Pre-Chat page" in Embedded Service Deployment.


Output:
 

August 13, 2021

Salesforce Connected App for SSO not working for Experiece Cloud/Community Cloud Users

 Check "IdP-Initiated Login URL" under "For Communities" section. For each Community/Experience Site, there will be separate IdP-Initiated Login URL.
 
 

August 12, 2021

How to return map containing custom metadata type records for the specific custom metadata type in Salesforce?

getAll() method can be used. 

1. Create a Custom Metadata Type.


2. Create few records.


Sample Code:
Map < String, Test__mdt > mapCustomMetadataType = Test__mdt.getAll();

for ( String strKey : mapCustomMetadataType.keySet() ) {
    
    system.debug( 'Key is ' + strKey );
    system.debug( 'Custom Metadata Type record is ' + mapCustomMetadataType.get( strKey ) );
    
}

Output:


How to queue Chats when all agents are busy in Salesforce?

Enable Queue in the Chat Button. Use Queue Size Per Agent or Overall Queue Size.
 
 

August 9, 2021

How to Initiate Chat in Salesforce using REST API?

1. Go to Chat Settings.


2. Get the Chat API Endpoint.


3. Get the Chat Button Id.


4. Get the Chat Deployment Id.


5. Get the Session Id.


6. Post using the Session Id to initiate the Chat.

 

Output:
 
 

August 6, 2021

How to add/remove Global search entities for Experience Cloud/Community Cloud in Salesforce?

 1. Open the Search Page.


2. Select the "Global Search Results" component and adjust.


Output:
 

How to prevent certain profile users to download files in Salesforce?

Sample Code:
public class ContentDownloadHandlerFactoryImpl implements Sfc.ContentDownloadHandlerFactory {

    public Sfc.ContentDownloadHandler getContentDownloadHandler( List<ID> listIds, Sfc.ContentDownloadContext context ) {
    
        Sfc.ContentDownloadHandler contentDownloadHandler = new Sfc.ContentDownloadHandler();
        
        system.debug( 'Inside the Content Download' );     
        Id profileId = UserInfo.getProfileId();
        
        if( String.isNotBlank( profileId ) ) {
        
            Profile objProfile = [ SELECT Id, Name FROM Profile WHERE Id =: profileId ];
            
            if ( objProfile != null && objProfile.Name == 'System Administrator' ) {
            
                contentDownloadHandler.isDownloadAllowed = false;
                contentDownloadHandler.downloadErrorMessage = 'Downloading a file is not allowed for your profile';
                return contentDownloadHandler;
            
            }
        
        }
    
        contentDownloadHandler.isDownloadAllowed = true;
        return contentDownloadHandler;
    
    }

}
 
Sample Code:


How to fetch data using External Id in Salesforce REST API?

End Point URL:
https://yourInstance.salesforce.com/services/data/v52.0/sobjects/ObjectAPIName/ExternalIdFieldAPI Name/ExternalIdValue

Example:
https://infallibletechie5-dev-ed.my.salesforce.com/services/data/v51.0/sobjects/Employee__c/Email__c/test2@testing.com
 
Workbench:
 
 
To use Postman client, use the below steps.
 
1. Create a Connected App. Update the Callback URL as per your domain URL.
 

2. Use the Consumer Key and Consumer Secret from the Connected app.

3. Do POST request and get the access token.


4. Do GET request with the access_token from step 3 and get the data.


August 5, 2021

How to create Case record only when Chat is transferred to an Agent in Salesforce Einstein Bot?

1. In the Embedded Chat, make sure only Contact is selected in the Pre-Chat.
 

2. Create a Flow to Create Case record and Update Chat Transcript with the Case Id.

Case Assignment:

Create Case:

Chat Transcript Assignment:

Update Chat Transcript:

3. Update "Transfer to Agent" Dialog in the BOT. Get the Subject for Case. Call the Flow to create a the Case and update Chat Transcript with the Case Id.