September 20, 2020

How to open Lightning Component from Commuity Builder in Salesforce?

1. Click Page Structure.

2. Click the Code Editor icon.



September 17, 2020

Order of events when a merge occurs in Salesforce

For example, 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.

Account Trigger:

trigger AccountTrigger on Account ( before delete, after delete, before update, after update ) {
    
    if( trigger.isDelete ) {
        
        if ( trigger.isBefore )
            system.debug( 'Before Delete in Account' );
        else if ( trigger.isAfter )
            system.debug( 'After Delete in Account' );
        
    } else if( trigger.isupdate ) {
        
        if ( trigger.isBefore )
            system.debug( 'Before update in Account' );
        else if ( trigger.isAfter )
            system.debug( 'After update in Account' );
        
    }

}

Opportunity Trigger:

trigger OpportunityTrigger on Opportunity ( before update, after update ) {
    
    if( trigger.isupdate ) {
        
        if ( trigger.isBefore )
            system.debug( 'Before update in Opportunity' );
        else if ( trigger.isAfter )
            system.debug( 'After update in Opportunity' );
        
    }

}

Contact Trigger:

trigger ContactTrigger on Contact ( before update, after update ) {
    
    if( trigger.isupdate ) {
        
        if ( trigger.isBefore )
            system.debug( 'Before update in Contact' );
        else if ( trigger.isAfter )
            system.debug( 'After update in Contact' );
        
    }

}


Output:



September 15, 2020

"This feature is not currently enabled either for this record type or the given user type or org" error when accessing Article from Salesforce Community

Switch to Classic if it is not available in Lightning Experience.
 
 
1. Open Topics for Objects from Setup.
 
 
2. Enable Topics for Knowledge object.
 
  

September 11, 2020

Salesforce Scheduled Flow

 
1. It runs as Automated Process User. So, use Automated Process User in Debug Logs.
 

 2. When calling Apex Class, it is bulkified.

Sample Code:

global class FlowSchedule {
    
    @InvocableMethod( label='Show Outputs' description='Getting multiple values' )
    global static List < FlowOutput > showOutputs( List < FlowInput > inputs ) {
        
        FlowInput objInput = inputs.get( 0 );
        List < FlowOutput > outputs = new List < FlowOutput >();
        for ( FlowInput inp : inputs ) {
            FlowOutput objOutput = new FlowOutput();
            objOutput.str3 = objInput.str1;
            objOutput.str4 = objInput.str2;
            outputs.add ( objOutput );
        }
        system.debug( 'outputs size is ' + outputs.size() );
        system.debug( 'outputs are ' + outputs );
        return outputs;
        
    }
    
    global class FlowInput {
        
        @InvocableVariable
        global String str1;
        
        @InvocableVariable
        global String str2;
        
    }
    
    global class FlowOutput {
        
        @InvocableVariable
        global String str3;
        
        @InvocableVariable
        global String str4;
        
    }
    
}
 
 
 


September 9, 2020

Freezing and Unfreezing multiple users or how to avoid multiple users logging into Salesforce

 IsFrozen in UserLogin is used for Freeze or unfreeze.

So, fetch the UserLogin records and mass update.

 
Data Loader can be used for Export and Import.

September 7, 2020

JavaScript Interview Questions with Answers Part 2

1. Numeric conversion, unary +
The plus + exists in two forms: the binary form that we used above and the unary form.
The unary plus or, in other words, the plus operator + applied to a single value, doesn’t do anything to numbers. But if the operand is not a number, the unary plus converts it into a number.

Example:
// No effect on numbers
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
// Converts non-numbers
alert( +true ); // 1
alert( +"" );   // 0

2. Increment/decrement
let counter = 1;
let a = ++counter;
alert(a); // 2
The prefix form ++counter increments counter and returns the new value, 2. So, the alert shows 2.

Now, let’s use the postfix form:
let counter = 1;
let a = counter++;
alert(a); // 1
The postfix form counter++ also increments counter but returns the old value (prior to increment). So, the alert shows 1.

If the result of increment/decrement is not used, there is no difference in which form to use:
let counter = 0;
counter++;
++counter;
alert( counter ); // 2, the lines above did the same

If we’d like to increase a value and immediately use the result of the operator, we need the prefix form:
let counter = 0;
alert( ++counter ); // 1

If we’d like to increment a value but use its previous value, we need the postfix form:
let counter = 0;
alert( counter++ ); // 0

3. Nullish coalescing operator '??'
The nullish coalescing operator ?? provides a short syntax for selecting a first “defined” variable from the list.

The result of a ?? b is:

    a if it’s not null or undefined,
    b, otherwise.

let a = null;
let b = null;
let c = "InfallibleTechie";

// show the first not-null/undefined value
alert(a ?? b ?? c ?? "XYZ"); // InfallibleTechie

4. function with no return statement in JavaScript

1. Without Return
function show() {
  alert( "Hello" );
}

alert( show );
alert( show() );

Output:
It will alert
function show() {
  alert( "Hello" );
}

It will alert
Hello

It will alert
Undefined

2. With Return
function show() {
  alert( "Hello" );
  return "Sample";
}

alert( show );
alert( show() );

Output:
It will alert
function show() {
  alert( "Hello" );
  return "Sample";
}

It will alert
Hello

It will alert
Sample

5. Function Expression vs Function Declaration

Function Declaration: a function, declared as a separate statement, in the main code flow.

// Function Declaration
function sum(a, b) {
  return a + b;
}

A Function Declaration can be called earlier than it is defined.

Function Expression: a function, created inside an expression or inside another syntax construct. Here, the function is created at the right side of the let sum = function(a, b) {
  return a + b;
};

A Function Expression is created when the execution reaches it and is usable only from that moment.

6. backtick quotes `
backtick quotes ` allow to split the string into multiple lines

var x = "testing
test";// is not allowed

var x = `testing
test`;//is allowed

7. What happens when an object variable is copied?
When an object variable is copied, the reference is copied and the object is not duplicated.

let user = { name: "John" };
let admin = user; // copies the reference

Now we have two variables, each one with the reference to the same object.

Two objects are equal only if they are the same object.

Here two variables reference the same object, thus they are equal:
let a = {};
let b = a; // copy the reference
alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true

And here two independent objects are not equal, even though both are empty:
let a = {};
let b = {}; // two independent objects
alert( a == b ); // false

Object.assign should be used to copy without reference.
let user = { name: "John" };
let user1 = Object.assign({}, user);
user1.name = "Cat";
alert(user.name); // John
alert( user1.name ); // Cat

8. this keyword
The value of this is evaluated during the run-time, depending on the context.

Arrow functions have no “this”
Arrow functions are special: they don’t have their “own” this. If we reference this from such a function, it’s taken from the outer “normal” function.

9. Constructor function
1. Constructor functions technically are regular functions.
2. They are named with capital letter first.
3. They should be executed only with "new" operator.

Example:
function User(name) {
  this.name = name;
  this.isAdmin = false;
}
let user = new User("John");
alert(user.name); // John
alert(user.isAdmin); // false

When a function is executed with new, it does the following steps:
1. A new empty object is created and assigned to this.
2. The function body executes. Usually it modifies this, adds new properties to it.
3. The value of this is returned.

But if there is a return statement, then the rule is simple:
1. If return is called with an object, then the object is returned instead of this.
2. If return is called with a primitive, it’s ignored.
In other words, return with an object returns that object, in all other cases this is returned.

Example:
Here return is primitive. So, this will be returned.
function User(name) {
  this.name = name;
  this.isAdmin = false;
  return "sample";
}
let user = new User("John");
alert(user.name); // John
alert(user.isAdmin); // false

Example:
Here return is an object. So, object will be returned.
function User(name) {
  this.name = name;
  this.isAdmin = false;
  return { name : "Frank" };
}
let user = new User("John");
alert(user.name); // Frank
alert(user.isAdmin); // undefined

10. Optional chaining '?.'
The optional chaining ?. is an error-proof way to access nested object properties, even if an intermediate property doesn’t exist.

Example: 
let user = {};
//alert(user.address.street); // Error!. If you uncomment this code. The exectuion will stop due to Type Error
alert( user?.address?.street );// Undefined

11. Symbol in JavaScript
Symbol is a primitive type for unique identifiers.

Object.getOwnPropertySymbols(obj) allows us to get all symbols. Also there is a method named Reflect.ownKeys(obj) returns all keys of an object including symbolic ones.

Symbols allow us to create “hidden” properties of an object, that no other part of code can accidentally access or overwrite.

Example:
let user = { // belongs to another code
  name: "Frank"
};
let id = Symbol("id");
user[id] = 1;
alert( user[id] ); // we can access the data using the symbol as the key

Symbols are skipped by for…in
Symbolic properties do not participate in for..in loop.

let id = Symbol("id");
let user = {
  name: "Frank",
  age: 30,
  [id]: 123
};

for (let key in user) alert(key); // name, age (no symbols)

// the direct access by the symbol works
alert( "Direct: " + user[id] );

12. Difference between Square brackets and charAt in JavaScript
The square brackets are a modern way of getting a character, while charAt exists mostly for historical reasons.

The only difference between them is that if no character is found, [] returns undefined, and charAt returns an empty string:

let str = `Hello`;alert( str[1000] ); // undefined
alert( str.charAt(1000) ); // '' (an empty string)

13. pop/push, shift/unshift methods in JavaScript

Push
push adds an element to the end.

Pop
pop takes an element from the end.
shift

Shift
Extracts/Removes the first element of the array and returns it.

Unshift
Add the element to the beginning of the array.

Methods push/pop run fast, while shift/unshift are slow.

14. splice and slice methods in JavaScript
Splice:
Syntax:

splice(index[, deleteCount, elem1, ..., elemN])

index - start index to delete
deleteCount - how many elements to delete
elem1, ...., elemN - Elements to add it to the Array. Adding starts from the index position mentioned.

Example
let arr = [0, 1, 2, 3, 4, 5];
arr.splice( 2, 2, "a", "b", "c", "d" );
alert( arr );//0, 1, a, b, c, d, 4, 5

Slice:
It returns a new array copying to it all items from index start to end (not including end)
Syntax:
slice([start], [end])

Example:
let arr = ["t", "e", "s", "t"];
alert( arr.slice(1, 3) ); // e,s (copy from 1 to 3)

15. JSON.stringify
To convert objects into JSON.
The method JSON.stringify() takes the object and converts it into a string.

Syntax:
JSON.stringify(value[, replacer, space])

value
    A value to encode.
replacer
    Array of properties to encode or a mapping function function(key, value).
space
    Amount of space to use for formatting

Example:
let user = {
  name: "John",
  interests: [ { sport : "Cricket" }, { sport: "Painting" } ]
};

let user1 = JSON.stringify( user, function replacer( key, value ) {
  if ( key == 'name' )
    return "Mathews";
    return value;
} );

alert( user1 );
Output:
{name: "John", interests: [{sport:"Cricket"},{sport:"Painting"}]}

Example:

let user = {
  name: "John",
  interests: [ { sport : "Cricket"}, { sport: "Painting"} ]
};

alert( JSON.stringify( user, [ "interests" ], 4 ) );
Output:
{
    "interests": [
        {},
        {}
    ]
}


Example:
let user = {
  name: "John",
  interests: [ { sport : "Cricket" }, { sport: "Painting" } ]
};

alert( JSON.stringify( user, [ "interests", "sport" ], 4 ) );
Output:
{
    "interests": [
        {
            "sport": "Cricket"
        },
        {
            "sport": "Painting"
        }
    ]
}

Example:
let user = {
  name: "John",
  interests: [ { sport : "Cricket" }, { sport: "Painting" } ]
};

alert( JSON.stringify( user, [ "interests", "sport", "name" ], 4 ) );
Output:
{
    "interests": [
        {
            "sport": "Cricket"
        },
        {
            "sport": "Painting"
        }
    ],
    "name": "John"
}

JSON.parse
To convert JSON back into an object.

Syntax:
JSON.parse(str, [reviver])

Example:
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';

let meetup = JSON.parse(str, function(key, value) {
  if (key == 'date') return new Date(value);
  return value;
});

alert( meetup.date.getDate() );//30. If the date is not converted using Date(), it will throw an error

lightning tree grid showing Account and its related Contacts and Opportunity in LWC in Salesforce

Sample Code:

HTML:


<template>
 
    <div class="slds-p-around_medium lgc-bg">

        <div class="slds-m-bottom_small">
            <lightning-button label="Expand All"
                              onclick={clickToExpandAll}>
            </lightning-button>
            <lightning-button label="Collapse All"
                              onclick={clickToCollapseAll}>
            </lightning-button>
        </div>

        <lightning-tree-grid columns={gridColumns}
                             data={gridData}
                             key-field="Id"
                             hide-checkbox-column=true>
        </lightning-tree-grid>
    </div>
 
</template>

JavaScript:

import { LightningElement, track, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/ExampleController.fetchAccounts';

export default class Example extends LightningElement {

    @track gridColumns = [{
        type: 'text',
        fieldName: 'Name',
        label: 'Name'
    },
    {
        type: 'text',
        fieldName: 'Industry',
        label: 'Industry'
    },
    {
        type: 'text',
        fieldName: 'FirstName',
        label: 'FirstName'
    },
    {
        type: 'text',
        fieldName: 'LastName',
        label: 'LastName'
    },
    {
        type: 'text',
        fieldName: 'OpptyName',
        label: 'Opportunity Name'
    },
    {
        type: 'text',
        fieldName: 'StageName',
        label: 'Opportunity Status'
    }];
    @track gridData;

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

        console.log( 'Inside wire' );
        if ( data ) {

            let tempData = JSON.parse( JSON.stringify( data ) );

            for ( let i = 0; i < tempData.length; i++ ) {
                
                let cons = tempData[ i ][ "Contacts" ];
                delete tempData[ i ][ "Contacts" ];
                let childRecords = cons;
                let opps = tempData[ i ][ "Opportunities" ];

                for ( let opp in opps ) {

                    opps[ opp ].OpptyName = opps [ opp ].Name;
                    delete opps [ opp ].Name;
                    childRecords.push( opps[ opp ] );

                }

                delete tempData[ i ][ "Opportunities" ];                
                console.log( 'Child Records ' + JSON.stringify( childRecords ) );
                tempData[ i ]._children = childRecords;

            }

            console.log( 'Final Data ' + JSON.stringify( tempData ) );
            this.gridData = tempData;

        } else if ( error ) {
           
            if ( Array.isArray( error.body ) )
                console.log( 'Error is ' + error.body.map( e => e.message ).join( ', ' ) );
            else if ( typeof error.body.message === 'string' )
                console.log( 'Error is ' + error.body.message );

        }

    }

    clickToExpandAll( e ) {
        const grid =  this.template.querySelector( 'lightning-tree-grid' );
        grid.expandAll();
    }

    clickToCollapseAll( e ) {
        const grid =  this.template.querySelector( 'lightning-tree-grid' );
        grid.collapseAll();
    }

}

Apex Class:

public with sharing class ExampleController {

    @AuraEnabled(cacheable=true)
    public static List < Account > fetchAccounts() {

        return [ SELECT Id, Name, Industry,
               ( SELECT Id, FirstName, LastName FROM Contacts ),
               ( SELECT Id, Name, StageName FROM Opportunities ) FROM Account LIMIT 5 ];
       
    }
   
}

Output:
 

 

Pass values from one Visualforce Page to Another Visualforce page in Salesforce

Visualforce Page:

<apex:page controller="AccountListController">
    
    <apex:form>
    
        <apex:pageBlock id="pg">
            
            <apex:pageBlockSection >
                <apex:panelGrid columns="3" cellpadding="3" cellspacing="3">
                    <apex:outputLabel value="Account Name: "/>
                    <apex:inputText value="{!acctName}"/>
                    <apex:commandButton value="Go" action="{!searchAcct}"/>
                </apex:panelGrid>
            </apex:pageBlockSection>
        
            <apex:pageBlockSection rendered="{!listAcct.Size > 0}" title="Accounts">        
                <apex:pageBlockTable value="{!listAcct}" var="acc">
                    <apex:column headerValue="Open Account Detail">
                        <apex:outputLink target="_blank" value="/{!acc.Id}">{!acc.Name}</apex:outputLink>
                    </apex:column>
                    <apex:column headerValue="Pass Account Id to a VF Page">
                        <apex:outputLink target="_blank" value="/apex/AccountDetail?accId={!acc.Id}">{!acc.Name}</apex:outputLink>
                    </apex:column>
                </apex:pageBlockTable>
            </apex:pageBlockSection>
            
        </apex:pageBlock>
        
    </apex:form>
        
</apex:page>

Apex Class:

public class AccountListController {
    
    public String acctName { get; set; }
    public List < Account > listAcct { get; set; }
    
    public AccountListController() {
        
        listAcct = new List < Account >();
        
    }
    
    public void searchAcct() {
        
        String soql = 'SELECT Id, Name FROM Account WHERE Name LIKE \'' + acctName + '%\' LIMIT 10';
        listAcct = Database.query( soql );
        
    }    

}

Visualforce Page:

<apex:page >
    
    <apex:detail subject="{!$CurrentPage.parameters.accId}"/>
    
</apex:page>

Output:


September 4, 2020

undefined error @wire in LWC in Salesforce

This error usually happens when cacheable=true is not set in the apex method. Check the below code that works without any issues since cacheable is set correctly.

public class AccountListController {
    
    @AuraEnabled(cacheable=true)
    public static List < Account > fetchAccts() {
        return [ SELECT Id, Name, Industry, Type FROM Account LIMIT 10 ];
    } 

}

September 3, 2020

How to get Salesforce Domain URL?

1. Go to My Domain in Setup.
 

2. Check the value in "Your domain name is".
 
 
So, the Domain URL will be https://infallible10-dev-ed.my.salesforce.com

September 2, 2020

Simple Time-Dependent Workflow Action in Salesforce

Below configuration with Workflow will send SLA Notification to the Account owner 30 day before the SLA Expiration Date. 

Email Template:


Email Alert:


Workflow Rule:

 To test

1. Open an Account Record.

2. Edit it and set Active to Yes and SLA Expiration Date to a future date.


3. Go to in Setup and click Search button.