October 28, 2020

Salesforce Data Loader Version Check

  

 


October 27, 2020

Searching Keyword using Salesforce Developer Console

1. Go to Edit --> Search in Files in Developer Console.


2. Enter the keyword and Search.



October 26, 2020

Case Feed in Salesforce Lightning

Case Feed is automatically on in Lightning Experience.
 
Check the below link for more information


October 24, 2020

How to get the deselected row(s) in lighting-datatable in LWC in Salesforce

Sample Code:

Apex Class:

public with sharing class AccountController {
 
    @AuraEnabled( cacheable = true )
    public static List< Account > fetchAccounts() {
     
        return [ SELECT Id, Name, Industry, AccountNumber, Rating, Type, Phone
                   FROM Account
                  LIMIT 100 ];
         
    }
     
}

HTML:
<template>
     
    <lightning-card title = "Accounts" icon-name = "custom:custom63">
 
        <div class = "slds-m-around_medium">
 
            <template if:true = {accounts}>
                 
                <div style="height: 300px;">
 
                    <lightning-datatable key-field="Id"
                                         data={accounts}
                                         columns={columns}  
                                         show-row-number-column="true"
                                         onrowselection={handleSelect}>
                    </lightning-datatable>
 
                </div>                  
     
            </template>
     
            <template if:true = {error}>
 
                {error}>
                 
            </template>
 
        </div>
 
    </lightning-card>
 
</template>

JavaScript:
import { LightningElement, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';
 
const columns = [   
    { label: 'Name', fieldName: 'Name' },
    { label: 'Industry', fieldName: 'Industry' }
];

export default class sample extends LightningElement() {
     
    accounts;
    error;
    columns = columns;
    selectedRows = [];
 
    @wire( fetchAccounts )  
    wiredAccount( value ) {

        this.wiredRecords = value; // track the provisioned value
        const { data, error } = value;

        if ( data ) {
                            
            this.accounts = data;
            this.error = undefined;

        } else if ( error ) {

            this.error = error;
            this.accounts = undefined;

        }

    }  

    handleSelect( event ) {

        const selRows = event.detail.selectedRows;
        console.log( 'Selected Rows are ' + JSON.stringify ( selRows ) );
        if ( this.selectedRows.length < selRows.length ) {

            console.log( 'Selected' );

        } else {

            console.log( 'Deselected' );
            let deselectedRecs = this.selectedRows
                 .filter(x => !selRows.includes(x))
                 .concat(selRows.filter(x => !this.selectedRows.includes(x)));

            console.log( 'Deselected Recs are ' + JSON.stringify( deselectedRecs ) );

        }
        this.selectedRows = selRows;

    }

}

Output:



October 23, 2020

How to restrict users to avoid entering characters other than alphabets and number in Salesforce Lightning Web Component?

Sample Code:
<template>
    <div class="slds-box slds-theme--default">
        <lightning-input
                        type="text"
                        label="String Only"
                        pattern="[a-zA-z0-9]+"
                        message-when-pattern-mismatch="Special Characters not allowed">
        </lightning-input>
    </div>
</template>

Output:



October 22, 2020

Deploy the in-app guidance in the Salesforce by creating the package XML

Metadata API entity is Prompt.
 
package.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>Prompt</name>
    </types>
    <version>47.0</version>
</Package>
 

October 20, 2020

SMS Channel - Messaging to Einstein Bot in Salesforce

1. Make sure you have Text channel added in Messaging Settings.


2. Make sure you have added the Text channel


Output:


Omni-Channel Limits in Salesforce

Navigate to Setup --> Omni-Channel --> Limits.


October 18, 2020

Email Quick Action in Salesforce Case object to remove To, CC, BCC and Subject fields(blank)

1. Create a Custom Quick Action and give value as blank for BCC Address, HTML Body, Subject and To Address.


2. Add the Quick Action to the Case page layout. When you use the Quick Action, To, BCC, Body and Subject will be blank. This allows users to enter their custom values to send emails.


October 17, 2020

How to clone EmailMessage record using Apex in Salefsorce?

Sample code:

EmailMessage objEM = [ SELECT BccAddress, BccIds, CcAddress, CcIds,
                              ContentDocumentIds,  
                                EmailTemplateId, FirstOpenedDate, FromAddress, FromName,
                                  HasAttachment, Headers, HtmlBody, Incoming, IsBounced,
                                  IsClientManaged, IsDeleted, IsExternallyVisible, IsOpened,
                                  IsTracked, LastOpenedDate, MessageDate,
                                  MessageIdentifier, ParentId, RelatedToId, ReplyToEmailMessageId,
                                  Status, Subject, TextBody, ThreadIdentifier, ToAddress,  
                                  ValidatedFromAddress
                         FROM EmailMessage WHERE Id = '<Id of the Record>' ];

EmailMessage objCloneEM = objEM.clone();
objCloneEM.HTMLBody = 'Testing';//Updating Body
objCloneEM.TextBody = 'Testing';//Updating Body
insert objCloneEM;

Opportunity Product/Opportunity Line Item access in Salesforce

Opportunity Product/Opportunity Line Item in Salesforce represent Product2 products associated with an Opportunity.

The user must have the “Edit” permission on Opportunity records to create or update opportunity line items on an opportunity.

To add or edit opportunity products, below permissions are required
1. Edit on opportunities
2. Read on products and price books

Check whether Opportunity field FLS is given to the profile
https://help.salesforce.com/articleView?type=1&mode=1&id=000317503

October 16, 2020

Automatically create a Contact when no contacts found or link existing Contact when new Message comes during Messaging in Salesforce

1. Go to Channel-Object Linking under Setup.



2. Click "New Linking Rule".

3. Select a Channel.

4. Select the Object.


5. Set the Linking Logic.
 
 
 

Case Comments Publisher in Salesforce Community - To add Case Comments quickly in Salesforce Community

1. Add Case Comments Publisher component.
 

 
2. Configure the Case Comments Publisher component.
 

 
3. Users can enter comments and click Comment button.
 

4. Users can view the case comments in Case Comment related list.


October 15, 2020

Collapsible and Expandable Case Comments using LWC in Salesforce

Sample Code:
 
HTML:
<template>
    
    <div class="slds-box slds-theme_default">
        <lightning-button label="Expand All"
                          onclick={handleClick}
                          name="Expand"
                          class="slds-m-left_x-small"></lightning-button>
        <lightning-button label="Collapse All"
                          onclick={handleClick}
                          name="Collapse"
                          class="slds-m-left_x-small"></lightning-button>
        <lightning-accordion allow-multiple-sections-open
                             active-section-name={sections}>
            <template iterator:it={records}>
                <lightning-accordion-section key={it.value.Id}
                                             label={it.value.strTitle}
                                             name={it.value.Id}>
                    {it.value.CommentBody}
                </lightning-accordion-section>
            </template>
        </lightning-accordion>
    </div>   

</template>

JavaScript:
import { LightningElement, api, wire } from 'lwc';
import fetchCaseComments from '@salesforce/apex/CaseCommentController.fetchCaseComments';

export default class caseCommentLWC extends LightningElement {

    @api recordId;
    records;
    error;
    sections;
    recIds = [];

    @wire( fetchCaseComments, { strRecId: '$recordId' } )  
    wiredCaseComments( { error, data } ) {

        if ( data ) {

            let rows = JSON.parse( JSON.stringify( data ) );
            console.log( 'Rows are ' + JSON.stringify( rows ) );
                
            for ( let i = 0; i < rows.length; i++ ) {  

                let dataParse = rows[ i ];
                dataParse.strTitle = dataParse.CreatedBy.Name + ' - ' + new Date( dataParse.CreatedDate ).toLocaleString();
                this.recIds.push( dataParse.Id );
                
            }
                
            this.records = rows;
            this.error = undefined;

        } else if ( error ) {

            this.error = error;
            this.records = undefined;
            this.recIds = [];

        }

    }

    handleClick( event ) {

        const buttonName = event.target.name;
        console.log( 'Button Name is ' + buttonName );

        switch( buttonName ) {

            case "Collapse":
                this.sections = [];
                break;

            case "Expand":
                this.sections = this.recIds;
                break;

        }

    }

}

meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>49.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
    <targetConfigs>     
        <targetConfig targets="lightning__RecordPage">     
            <property name="recordId" type="String" label="Record Id" description="Record Id"/>     
        </targetConfig>   
    </targetConfigs>   
</LightningComponentBundle>

Apex Class:
public with sharing class CaseCommentController {
    
    @AuraEnabled( cacheable=true )
    public static List < CaseComment > fetchCaseComments( String strRecId ) {

        return [ SELECT Id, CommentBody, CreatedBy.Name, CreatedDate
                  FROM CaseComment
                 WHERE ParentId =: strRecId
                 ORDER BY CreatedDate DESC];
        
    }

}

Output:


October 14, 2020

Case Comment Notification in Salesforce Community

1. Go to All Communities under setup.

2. Open the Community.

3. Click Workspace.

4. Click Administration.

5. Select Email.

6. Under Email Templates section, select an email template in "Case Comment".


October 13, 2020

Drop Down Box or Combo Box to filter data in custom table using LWC in Salesforce

Sample Code:

HTML:

<template>
    <div class="slds-box slds-theme--default">
        <div class="slds-text-color_inverse slds-text-heading_large" style="padding:0.5rem;background:#16325c">        
            Accounts
        </div>
        <div style="width:200px; padding:0.5rem;">
            <lightning-combobox name="filter"
                                label="Status"
                                value={selectedValue}
                                variant="label-hidden"
                                options={options}
                                onchange={handleChange}
                                placeholder="Select Industry to filter"></lightning-combobox>
        </div>
        <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped">
            <thead>
                <tr class="slds-line-height_reset">
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Name">
                            Account Name
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="AccountNumber">
                            Account Number
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Industry">
                            Industry
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Rating">
                            Rating
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Type">
                            Type
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Phone">
                            Phone
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
                <template iterator:it={records}>
                    <tr class="slds-hint-parent" key = {it.value.Id}>
                        <td data-label="Account Name">
                            <div class="slds-cell-wrap">{it.value.Name}</div>
                        </td>
                        <td data-label="Account Number">
                            <div class="slds-cell-wrap">{it.value.AccountNumber}</div>
                        </td>
                        <td data-label="Industry">
                            <div class="slds-cell-wrap">{it.value.Industry}</div>
                        </td>
                        <td data-label="Rating">
                            <div class="slds-cell-wrap">{it.value.Rating}</div>
                        </td>
                        <td data-label="Type">
                            <div class="slds-cell-wrap">{it.value.Type}</div>
                        </td>
                        <td data-label="Phone">
                            <div class="slds-cell-wrap">{it.value.Phone}</div>
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </div>
</template>

JavaScript:
import { LightningElement, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';

export default class Sample extends LightningElement {

    records;
    sortedColumn;
    sortedDirection;
    selectedValue = 'All';

    get options() {
        return [
            { label: 'All', value: 'All' },
            { label: 'Apparel', value: 'Apparel' },
            { label: 'Biotechnology', value: 'Biotechnology' },
            { label: 'Construction', value: 'Construction' },
            { label: 'Consulting', value: 'Consulting' },
            { label: 'Energy', value: 'Energy' }
        ];
    }

    handleChange( event ) {

        this.selectedValue = event.detail.value;
        if ( this.selectedValue === 'All' )
            this.records = this.initialRecords;
        else
            this.filter();

    }

    @wire( fetchAccounts )  
    wiredAccount( { error, data } ) {

        if (data) {

            this.records = data;
            this.initialRecords = data;
            this.error = undefined;
            this.sortedColumn = "Name";
            this.sortRecs();

        } else if ( error ) {

            this.error = error;
            this.initialRecords = undefined;
            this.records = undefined;

        }

    }  

    sortRecs( event ) {

        let colName = event ? event.target.name : undefined;
        console.log( 'Column Name is ' + colName );

        if ( this.sortedColumn === colName )
            this.sortedDirection = ( this.sortedDirection === 'asc' ? 'desc' : 'asc' );
        else
            this.sortedDirection = 'asc';

        let isReverse = this.sortedDirection === 'asc' ? 1 : -1;

        if ( colName )
            this.sortedColumn = colName;
        else
            colName = this.sortedColumn;

        this.records = JSON.parse( JSON.stringify( this.records ) ).sort( ( a, b ) => {
            a = a[ colName ] ? a[ colName ].toLowerCase() : 'z';
            b = b[ colName ] ? b[ colName ].toLowerCase() : 'z';
            return a > b ? 1 * isReverse : -1 * isReverse;
        });

    }

    filter() {  
           
        if ( this.selectedValue ) {  

            this.records = this.initialRecords;
 
            if ( this.records ) {

                let recs = [];
                for ( let rec of this.records ) {

                    console.log( 'Rec is ' + JSON.stringify( rec ) );

                    if ( rec.Industry === this.selectedValue ) {

                        recs.push( rec );
                
                    }
                    
                }

                console.log( 'Recs are ' + JSON.stringify( recs ) );
                this.records = recs;

            }
 
        }  else {

            this.records = this.initialRecords;

        }
 
    }  

}

Apex Class:
public with sharing class AccountController {
 
    @AuraEnabled( cacheable = true )
    public static List< Account > fetchAccounts() {
     
        return [ SELECT Id, Name, Industry, AccountNumber, Rating, Type, Phone
                   FROM Account
                  LIMIT 10 ];
         
    }
     
}

Output:



October 10, 2020

How to save the custom detail to a custom field on Chat Transcript object(LiveChatTranscript) in Salesforce?

Chat Transcript object have several standard fields. For Example, Chat Button in Chat Transcript object stores the chat button id that the visitor clicked to initiate the chat.
Reference Link:
https://help.salesforce.com/articleView?id=live_agent_transcript_fields.htm&type=5

To save the custom detail to a custom field on LiveChatTranscript at the end of a chat, use the below
liveagent.addCustomDetail().saveToTranscript()

Example:
liveagent.addCustomDetail( 'Company', 'Acme' ).saveToTranscript( 'Company__c' );
Here Company__c is a custom field in Chat Transcript Object.

Sample Code:
<script type='text/javascript'>
var test = liveagent.addCustomDetail( 'Example', 'Example Value' ).saveToTranscript( 'Source__c' );
</script>
 

Salesforce Interview Questions with Answers Part 65

1. Fault Connector in Salesforce Flow
While a connector element determines the normal path of flow execution, a fault connector is executed at runtime only when its source element results in an error.
This can be used for Exception Handling in Flows.
User-friendly messages can be shown to avoid confusion to the user when there is an exception in Flow execution.
It can be used to handle errors/exceptions.

2. Getter and Setter
A getter executes logic when a property is read. A setter executes logic when a property is written to.

3. What is the output of ("10" / 2) * "5" - "2" + "5" in JavaScript?
Answer is 235
("10" / 2) = 5
"5" * "5" = 25
25 - "2" = 23
23 + "5" = 235 (string concatenation)

Reason:
All arithmetic operators except '+' auto-casts operands to Number type. While '+' defaults to string concatenation if one of the operands is a string.

4. Permission to create Campaign in Salesforce
Marketing User check box on the user detail is required to create Campaigns.
Marketing Users can view, create, edit, and delete Campaigns as long as they have the “Read,” “Create,” “Edit,” and “Delete” permissions for Campaigns in the Profile.
Users that don't have the Marketing User checkbox selected only have access to view Campaigns and advanced Campaign setup, edit the Campaign History for a single lead or contact, and run Campaign reports if they have the “Read” permission for Campaigns.

5. lightningStylesheets, apex:slds and apex:includeLightning
lightningStylesheets="true" - Make Visualforce apps look better in Lightning.
<apex:slds/> - To use markup specified by SLDS in Visualforce page.
<apex:includeLightning/>
There are three steps to add Aura components to a Visualforce page.
Add the Lightning Components for Visualforce JavaScript library to your Visualforce page using the <apex:includeLightning/> component.
Create and reference a Lightning app that declares your component dependencies.
Write a JavaScript function that creates the component on the page using $Lightning.createComponent().

6. renderUsingSystemContextWithoutSharing="True"
When renderUsingSystemContextWithoutSharing="True", the email template runs in system mode, which bypasses user permissions, field-level security, and organization-wide defaults. Be careful when using this setting so that you don't inadvertently expose sensitive data. Before using this setting, assess the impact of the guest security policy and, if necessary, update the Visualforce email templates instead.

In Summer ‘20, Salesforce introduced a security policy that affects Visualforce email templates used to send emails to guest users in communities.

7. Process Builder Best Practice in Salesforce 
For each object, use one automation tool. If an object has one process, one Apex trigger, and three workflow rules, you can’t reliably predict the results of a record change.


8. Events communication in Salesforce LWC

Lightning web components dispatch standard DOM events. Components can also create and dispatch custom events. Use events to communicate up the component containment hierarchy. For example, a child component, c-todo-item, dispatches an event to tell its parent, c-todo-app, that a user selected it.

Create and Dispatch Events
Create and dispatch events in a component’s JavaScript class. To create an event, use the CustomEvent() constructor. To dispatch an event, call the EventTarget.dispatchEvent() method.

The CustomEvent() constructor has one required parameter, which is a string indicating the event type. As a component author, you name the event type when you create the event. You can use any string as your event type. However, we recommend that you conform with the DOM event standard.

No uppercase letters
No spaces
Use underscores to separate words

Don’t prefix your event name with the string on, because inline event handler names must start with the string on. If your event is called onmessage, the markup would be <c-my-component ononmessage={handleMessage}>. Notice the doubled word onon, which is confusing.

9. Private Connect in Salesforce
When you want to integrate third-party services with Salesforce, it’s essential to be able to communicate securely. With Private Connect, you can increase security on your HTTP/s traffic by setting up a fully managed secure connection between Salesforce data centers and Amazon Web Services (AWS). API calls that run through AWS PrivateLink don’t traverse the internet, reducing exposure to outsider security threats.

In AWS, Salesforce VPC will do the callouts so that it won't go to the outside internet.

10. Send Email to Members in Salesforce Queue

An Email is sent to all Queue members individually when new records are placed in the Queue if:

1. The Queue Email field is left Blank regardless if the 'Send Email to Members' checkbox is selected or notOR

2. When there is a Queue Email specified AND the 'Send Email to Members' checkbox is selected.

The Send Email to queue members alert will only work if you are using Case Assignment Rules and Active Assignment checkbox to move Case to a Queue. If you are moving the case Manually to a Queue or using a Workflow, it does not trigger the Email alert. The Email is also triggered when a Lead is created from a Web-to-Lead form.

Referece Link - https://help.salesforce.com/articleView?id=000323036&type=1&mode=1

11. Calling Apex from LWC
To call an Apex method, a Lightning web component can:

1. Wire a property
2. Wire a function
3. Call a method imperatively

Whether you use @wire or call a method imperatively, the data is stored in the Lightning Data Service cache. However, data provisioned by Apex is not managed by Lightning Data Service. If you use @wire to call an Apex method, refresh data using refreshApex() when data gets stale. If you call an Apex method imperatively, refresh data by invoking the Apex method again.

When you call a method imperatively, you receive only a single response. Compare this behavior with @wire, which delegates control to the framework and results in a stream of values being provisioned.

Imperative Call:
import { LightningElement, track } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

export default class ApexImperativeMethod extends LightningElement {
    @track contacts;
    @track error;

    handleLoad() {
        getContactList()
            .then(result => {
                this.contacts = result;
            })
            .catch(error => {
                this.error = error;
            });
    }
}

@wire a property:
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
@wire(apexMethodName, { apexMethodParams })
propertyOrFunction;

@wire a function:
import { LightningElement, wire } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

export default class ApexWireMethodToFunction extends LightningElement {
    contacts;
    error;

    @wire(getContactList)
    wiredContacts({ error, data }) {
        if (data) {
            this.contacts = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.contacts = undefined;
        }
    }
}

12. Order of events when a merge occurs in Salesforce
If two contacts are merged, only the delete and update contact triggers fire. No triggers for records related to the contacts, such as accounts or opportunities, fire.

1. The before delete trigger fires.
2. The system deletes the necessary records due to the merge, assigns new parent records to the child records, and sets the MasterRecordId field on the deleted records.
3. The after delete trigger fires.
4. The system does the specific updates required for the master record. Normal update triggers apply.

13. Use Salesforce Knowledge in Lightning Community
Salesforce Knowledge uses data categories to organize content. Lightning communities use topics. You can easily map the articles in your data categories to topics in a community. To map articles to topics automatically: In Experience Workspaces, click Content Management | Topics | Automatic Topic Assignment.

14. How to save the custom detail to a custom field on Chat Transcript object?
To save the custom detail to a custom field on LiveChatTranscript at the end of a chat, use the below
liveagent.addCustomDetail().saveToTranscript()

Example:
liveagent.addCustomDetail( 'Company', 'Acme' ).saveToTranscript( 'Company__c' );
Here Company__c is a custom field in Chat Transcript Object.
 
Reference Link:
https://developer.salesforce.com/docs/atlas.en-us.live_agent_dev.meta/live_agent_dev/live_agent_deployment_api_code_sample.htm

15. How to pass values from Start Chat button to Pre-Chat form in Salesforce?
To Pass values from Start Chat button to Pre-Chat Form, use addCustomDetail().
Example:
liveagent.addCustomDetail('test','Test Value');

Use details attribute to capture the values in Pre-Chat form.

Reference Link:
https://help.salesforce.com/articleView?id=000338336&type=1&mode=1

October 9, 2020

How to hyperlink Parent Record Details in custom data table with iterator in Salesforce LWC?

Sample Code:

HTML:

<template>
    <div class="slds-box slds-theme--default">
        <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped">
            <thead>
                <tr class="slds-line-height_reset">
                    <th class="" scope="col">
                        Account Name
                    </th>
                    <th class="" scope="col">
                        Account Number
                    </th>
                    <th class="" scope="col">
                        Owner
                    </th>
                </tr>
            </thead>
            <tbody>
                <template iterator:it={records}>
                    <tr class="slds-hint-parent" key = {it.value.Id}>
                        <td data-label="Account Name">
                            <div class="slds-cell-wrap">{it.value.Name}</div>
                        </td>
                        <td data-label="Account Number">
                            <div class="slds-cell-wrap">{it.value.AccountNumber}</div>
                        </td>
                        <td data-label="Owner">
                            <div class="slds-cell-wrap">
                                <a href={it.value.OwnerURL}>
                                    {it.value.OwnerName}
                                </a>
                            </div>
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </div>
</template>

JavaScript:
import { LightningElement, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';

export default class Sample extends LightningElement {

    records;
    error;

    @wire( fetchAccounts )  
    wiredAccount( { error, data } ) {
        if ( data ) {

            let rows = JSON.parse( JSON.stringify( data ) );
            console.log( 'Rows are ' + JSON.stringify( rows ) );
                
            for ( let i = 0; i < rows.length; i++ ) {  

                let dataParse = rows[ i ];
                dataParse.OwnerName = dataParse.Owner.Name;
                dataParse.OwnerURL = "/" + dataParse.OwnerId;
                
            }
                
            this.records = rows;
            this.error = undefined;

        } else if ( error ) {

            this.error = error;
            this.records = undefined;

        }
    }  

}

Apex Class:
public with sharing class AccountController {
 
    @AuraEnabled( cacheable = true )
    public static List< Account > fetchAccounts() {
     
        return [ SELECT Id, Name, Industry, Rating, Type, AccountNumber, Phone, Owner.Name, OwnerId FROM Account LIMIT 10 ];
         
    }
     
}


Output:



lightning datatable inline editing using LWC in Salesforce

Sample Code:

HTML:

<template>
    <lightning-card>
        <div class="slds-m-around_medium">
            <lightning-datatable
                    key-field="Id"
                    data={records}
                    columns={columns}
                    hide-checkbox-column
                    draft-values={draftValues}
                    onsave={handleSave}>
            </lightning-datatable>
        </div>
    </lightning-card>
</template>

JavaScript:
import { LightningElement, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';
import updateAccounts from '@salesforce/apex/AccountController.updateAccounts';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

const columns = [
    { label: 'Name', fieldName: 'Name', editable: true },
    { label: 'Industry', fieldName: 'Industry', editable: true },
    { label: 'Effective Date', fieldName: 'Effective_Date__c', type: 'date-local', editable: true, typeAttributes: {  
                                                                                                day: 'numeric',  
                                                                                                month: 'numeric',  
                                                                                                year: 'numeric'} }
];

export default class Sample extends LightningElement {

    records;
    wiredRecords;
    error;
    columns = columns;
    draftValues = [];

    @wire( fetchAccounts )  
    wiredAccount( value ) {

        this.wiredRecords = value; // track the provisioned value
        const { data, error } = value;

        if ( data ) {
                            
            this.records = data;
            this.error = undefined;

        } else if ( error ) {

            this.error = error;
            this.records = undefined;

        }

    }  

    async handleSave( event ) {

        const updatedFields = event.detail.draftValues;

        await updateAccounts( { data: updatedFields } )
        .then( result => {

            console.log( JSON.stringify( "Apex update result: " + result ) );
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Account(s) updated',
                    variant: 'success'
                })
            );
            
            refreshApex( this.wiredRecords ).then( () => {
                this.draftValues = [];
            });        

        }).catch( error => {

            console.log( 'Error is ' + JSON.stringify( error ) );
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error updating or refreshing records',
                    message: error.body.message,
                    variant: 'error'
                })
            );

        });

    }

}

Apex Class:
public with sharing class AccountController {
 
    @AuraEnabled( cacheable = true )
    public static List< Account > fetchAccounts() {
     
        return [ SELECT Id, Name, Industry, Effective_Date__c FROM Account LIMIT 10 ];
         
    }

    @AuraEnabled
    public static string updateAccounts( Object data ) {
        
        List < Account > accsForUpdate = ( List < Account > ) JSON.deserialize(
            JSON.serialize( data ),
            List < Account >.class
        );
        try {
            update accsForUpdate;
            return 'Success: Account(s) updated successfully';
        }
        catch (Exception e) {
            return 'The following exception has occurred: ' + e.getMessage();
        }

    }
     
}

Output:



October 8, 2020

Data Masking in Salesforce

Below are some of the options for Data Masking in Salesforce

1. Use Salesforce Data Mask(Recommended process for easy and fast data masking) -

https://trailhead.salesforce.com/en/content/learn/modules/salesforce-data-mask

https://www.infallibletechie.com/2020/02/salesforce-data-mask.html

2. We can manually use Data Loader tool to update sensitive information(time consuming process).

3. We can also make use of tools like CommVault, AutoRabit DataloaderPro, OwnBackup, etc.

October 6, 2020

Salesforce Find and Create Records Pre-Chat API

In this blog post, below requirements are handled through Pre-Chat API

1. Creating Contact

2. Creating Case

3. Linking Case to the Contact

4. Linking Case and Contact to the Chat Transcript

5. Showing the Case and Contact in Service Console app as sub-tabs

Chat Deployment: 

Sample VF Page Code:

<apex:page showHeader="false" standardStylesheets="false" sidebar="false" title="Pre-Chat Form" cache="false">

    <!-- form id should be used in getElementById() -->
    <script type="text/javascript">
        (function() {
            function handlePageLoad() {
                var endpointMatcher = new RegExp("[\\?\\&]endpoint=([^&#]*)");
                document.getElementById('prechatForm').setAttribute('action',
                        decodeURIComponent(endpointMatcher.exec(document.location.search)[1]));
            }
            if (window.addEventListener) {
                window.addEventListener('load', handlePageLoad, false);
            } else {
                window.attachEvent('onload', handlePageLoad, false);
            }
        })();
    </script>

    <form method='post' id='prechatForm'>
        <table cellspacing="5" cellpadding="5">
            <tr>
                <td>First Name</td>
                <td><input type='text' name='liveagent.prechat:ContactFirstName' /></td>
            </tr>
            <tr>
                <td>Last Name</td>
                <td><input type='text' name='liveagent.prechat:ContactLastName' /></td>
            </tr>
            <tr>
                <td>Email</td>
                <td><input type='text' name='liveagent.prechat:ContactEmail' /></td>
            </tr>
            <tr>
                <td>Subject</td>
                <td><input type='text' name='liveagent.prechat:CaseSubject' /></td>
            </tr>
        </table>
        <!-- Contact creation Start -->
        <input type="hidden" name="liveagent.prechat.findorcreate.map:Contact" value="FirstName,ContactFirstName;LastName,ContactLastName;Email,ContactEmail" />
        <input type="hidden" name="liveagent.prechat.findorcreate.map.doFind:Contact" value="FirstName,true;LastName,true" />
        <input type="hidden" name="liveagent.prechat.findorcreate.map.isExactMatch:Contact" value="FirstName,true;LastName,true" />
        <input type="hidden" name="liveagent.prechat.findorcreate.map.doCreate:Contact" value="FirstName,true;LastName,true;Email,true" />
        <!-- Contact creation End -->
        <!-- Case creation Start -->
        <!-- Setting Case Status and Origin -->
        <input type="hidden" name="liveagent.prechat:CaseStatus" value="New" /><br />
        <input type="hidden" name="liveagent.prechat:CaseOrigin" value="Chat" /><br />
        <input type="hidden" name="liveagent.prechat.findorcreate.map:Case" value="Subject,CaseSubject;Status,CaseStatus;Origin,CaseOrigin" />
        <input type="hidden" name="liveagent.prechat.findorcreate.map.doCreate:Case" value="Subject,true;Status,true;Origin,true" />
        <!-- Case creation End -->
        <!-- Linking Contact and Case to the Chat Transcript -->
        <input type="hidden" name="liveagent.prechat.findorcreate.saveToTranscript:Contact" value="ContactId" />
        <input type="hidden" name="liveagent.prechat.findorcreate.saveToTranscript:Case" value="CaseId" />
        <!-- Showing the Contact and Case when the Chat loads automatically in a subtab in the Salesforce console -->
        <input type="hidden" name="liveagent.prechat.findorcreate.showOnCreate:Contact" value="true" />
        <input type="hidden" name="liveagent.prechat.findorcreate.showOnCreate:Case" value="true" />
        <!-- Linking Case to the Contact -->
        <input type="hidden" name="liveagent.prechat.findorcreate.linkToEntity:Contact" value="Case,ContactId" />
        <input type="submit" value="Submit"/>
    </form>

</apex:page>

Chat Button:

Note:

Make sure the VF page is added to the Site's Guest Profile Access.

Output: