Tuesday, 26 May 2020

LWC Component Bundle | Build your first component | Core Concepts

In my previous blog, I explained all the pre-requisite steps to set up the LWC development environment on your system.

Now I'll explain


  1. How to create your fist lightning web component?
  2. Significance of each component bundle file.
  3. Enable My domain and Dev Hub.
  4. Create scratch org
  5. Deploy component to Org or Scratch org


Create Lightning Web component:

Create Project:

Open Visual Studio Code > Open command pallet by pressing 'Ctrl + Shift + P ' and run follwing command > Select 'SFDX: Create Project' > Enter Project name for exmaple : 'SalesforceTechnoWarrior'



Create Lightning Web Component

run command > 'SFDX: Create Lightning web component' > Enter component name (helloSalesforce) > Select 'force-app\main\default' as directory.

It will create a lwc component.

Note: As best practice component name should be in CAMEL case.



Component bundle

No alt text provided for this image
Our lwc component by default has 3 files: .html, .js and meta.xml.

We can also add additonal .css, .svg


1. .html file:

It holds the markup of your component. You can write normal HTML tags or lightning component elements inside <template> tag.


Everything will come under <template> tag only.

2. .js file:

It defines business logic and event handling like On click of a button, on page load, get data from Salesforce object, etc.




  • JS file by default has 2 statements - import and export.
  • Import statement: is used to import any ECMA script module in the lightning web component.
  • 'lwc' is a module and we are importing 'LightningElement' property from lwc module so that we can use it to construct our custom component. We can also import other properties from 'lwc' module like track, api, wire etc. We can also write multiple import statements as well.
import { LightningElement,track,api,wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';


  • Now we use 'Export' statement to use variables(other code to use a class, function, or variable) declared in the module ('lwc').
All of our client-side logic will come under this {} parenthesis. So you need to declare all of your properties and methods here.

Note: Our component file name is in CAMEL case (helloSalesforce) and our class name is in PASCAL case (HelloSalesforce). 



3. meta.xml file:

Every component must have a meta config file. It defines the metadata values for the component like

  • Design configuration properties, allowing lwc to be available in the lightning app builder.
  • We can target lwc components to Record Page, App Page, Hom page, Community Page, Utility bar, Lightning tab, etc by using <target> tag


Check above screenshot of meta.xml file

Point 1: <isExposed> is set to true to exposes the component in all orgs, and in Lightning App Builder, Community Builder, and managed packages. It makes the component available from other namespaces.

Point 2: Using <masterLabel> and <description> tag we can provide some meaningful label and description to our custom lwc component which can be seen by admin in the lightning app builder.

Point 3: Using <target> tag we can specify where admin can add lwc component like Account record page, app page, or community page.

Point 4: Using <property> We can define configurable/custom properties to make generic components. While adding this component to page, admin can set values for it.

When we deploy our component to Org then while adding it to any app page we can see the following important things:



4. .css file:

Additionally, we can add a .css file to lwc component folder to define our custom UI styles. CSS file name should be same as the component name.



Right-click on lwc component folder name > Add file > enter file name as 'helloSalesforce.css' > Add your classes like normal css styles.


5. .svg file:

Scalable Vector Graphics is an XML-based image format. It is an icon which is visible in lightning app builder same as in AURA components.



Code for Lightning Web Component

Now we have a deep understanding of each file of lwc component. Lets copy-paste following code into your LWC component:

helloSalesforce.html


<template>
    <!--html elements-->
        <h2>Hello Salesforce</h2>
        <p>This is my first lightning web component </p>
        <div>Keep Learning...Keep Sharing...!!!</div>
    
    <!--lightning elements-->
    <lightning-card  title={prop1}>
        <lightning-button label="New" slot="actions"></lightning-button>
        <p class="slds-p-horizontal_small">LWC Component Bundle | Build your first component</p>
        <p slot="footer">Follow me on Linkedin : sud-gupta</p>
    </lightning-card>
    
</template>


helloSalesforce.js

import { LightningElement, track,api, wire } from 'lwc';


export default class HelloSalesforce extends LightningElement {
    /*
        All our properties and methods will come here 
    */
   @api prop1 = 'Salesforce Techno Warrior'; // Defining default value for configurable property 
   @api prop2 = false;
   //To expose a public property, decorate it with @api.

helloSalesforce.js-meta.xml


<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
  <apiVersion>47.0</apiVersion>
  <isExposed>true</isExposed>
  <masterLabel>Hello Salesforce Component</masterLabel>
  <description>Here we specify component description component.</description>
  <targets>
      <target>lightning__RecordPage</target>
      <target>lightning__AppPage</target>
      <target>lightning__HomePage</target>
      <target>lightningCommunity__Page</target>
  </targets>
  <targetConfigs>
      <targetConfig targets="lightning__AppPage,lightning__RecordPage">
          <property name="prop1" type="String" /> 
          <property name="prop2" type="Boolean" />         
      </targetConfig>      
  </targetConfigs>
</LightningComponentBundle>



helloSalesforce.css 

(right-click on lwc folder name and add new file componentName.css)

h2{
    font-size: large;
    color: blue;
    background-color:white; 
}
p{
   background-color:white;
   font-size: medium;
}
div{
    border-bottom: 1px solid grey;
    width:100%;
    font-size: large;
    color:tomato;
    background-color:rgb(235, 233, 233);
    margin-bottom: 20px;
}

Enable My domain and Dev Hub.

Before we deploy our component to salesforce, we need to make sure my domain and dev are enabled/configured in salesforce org. 
Follow this video to create free developer of, enable my domain and dev hub.

 

Deploy LWC Component to your Org

We can deploy lwc components to scratch org (short-lived org for testing purpose) or main org. Here we will be deploying to our developer org (main org).



Ctrl + Shift + P > run following command :

  1. SFDX: Authorize an Org : Login with your salesforce org. (you can skip alias name)
  2. SFDX: Deploy This Source to Org
Add this component to Lightning app page.

Setup > Lightning app builder > Create a new App page > edit page > find 'Hello salesforce component' in custom list > drag it to page > save > activate




Keep Learning ... Keep Sharing...!!!

Tuesday, 19 May 2020

Reset security token for Salesforce Integration



A security token is a case-sensitive alphanumeric code that we append to our password or enter in a separate field in a client application. We use it (user password + security token) to authenticate with salesforce from an external system. When we change our password, the security token is also regenerated.

In the production environment, we usually have a separate user with a profile having 'password never expire' option selected.

Ideally, in order to generate a security token, we need to go to:

Click on user icon > Settings > search for 'Reset My Security Token' > Click 'Reset Security Token' and then a new security token is sent to the email address. 

But what to do if that option is not available in the personal user settings?




Recently I came across a similar situation, I was having system administrator profile and there was no IP restriction as well. I was not able to see the option 'Reset My Security Token' in personal user settings.

I came across a URL hack using which we can easily use to generate/re-generate our security token.

You need to append following URL to your org sandbox instance URL:

https://<YourDomain>.lightning.force.com + /_ui/system/security/ResetApiTokenEdit?retURL=%2Fui%2Fsetup%2FSetup%3Fsetupid%3DPersonalInfo&setupid=ResetApiToken




Check out my short video for more details.



Keep Learning...!!! Keep Sharing...!!!

Follow me on Linkedin: sud-gupta

Friday, 15 May 2020

Prerequisites to start development for Lightning web components (LWC) - Salesforce

In this blog I will talk about the following things:

  1. What are Lightning web components (LWC)?
  2. Why we need LWC over old Aura components? plus new browser web standards.
  3. Prerequisite to start LWC development: Installing and configuring: 
  • Visual Studio Code (VS Code)
  • Command Line Interface
  • Installing Java SDK
  • VS Code Extensions
Enable Dev Hub. What are Scratch Orgs?





Check out all details here: link

Friday, 1 May 2020

Restrict upload of particular files types in FILES related list- Salesforce lightning

Sometimes we need to restrict the 'Type' of a file which end-user can upload to  'Files' related list of any salesforce record in lightning experience for example

  1. Allow only word, pdf, images and text files  
  2. Restrict .zip, .exe files etc (any particular file format) 
Here I'll be implementing and explaining:

Requirement: Account object has 'Banking' record type. User should not be able to upload '.pdf' files in 'Files' related list for banking account records.


Quick overview video




Before we proceed to implementation, we should know a few important things: 
  1. In lightning, 'Attachment' has been replaced by 'Files/Content'. 'Files' related list also shows attachments (uploaded previously via classic experience) if there is any. 
  2. If a document is uploaded in Lightning experience, it becomes part of Files/Content object. If the user switches to classic experience and uploads any document to 'Notes and Attachment' related list then it goes to 'Attachment' object. 
  3.  ContentDocument: This object record we don’t create. It gets created when we create Content Version who is a child of ContentDocument. But Id of this record will be required to do other stuff.
  4. ContentVersion: This is where our attachment will be inserted but still it will not be visible under Attachment/Files related list. For that, we need to create ContentDocumentLink.
  5. ContentDocumentLink: It will share the files with users, records, groups etc and create files under your object records You can create multiple records to attach the same files under multiple records.

What we need to do to meet the requirement?

  1. Create a trigger on 'ContentDocumentLink' object and utilizing after insert event.
  2. Loop through ContentDocumentLink records.
  3. Check 'LinkedEntityId' i.e. if the document is associated with an Account record or something else.
  4. Check for RecordType
  5. Finally restricting by using .addError(); 
 Trigger Code: 

// Trigger on ContentDocumentLink object : Created by Sudhanshu Gupta - SalesForce Technical Warrior
trigger trig_ContentDocumentLink_AfterInsert on ContentDocumentLink (after insert) {
   if(Trigger.isAfter && Trigger.isInsert){
      System.debug('SFDC Tech Warrior... Trigger started after insert.');
      TW_ContentDocumentLink_Handler.onAfterInsert(Trigger.New);  
    }
}


********************************************************************************
Helper Class Code:

/* 
Class : TW_ContentDocumentLink_Handler
Description: Called from trigger - 'trig_ContentDocumentLink_AfterInsert', after insert case.   
in Banking type account (Record Type) Restrict pdf files upload through 'Upload Files' button present in Notes and Attachments  
Owner : Sudhanshu Gupta Technical Warrior- 2020
*/

public class TW_ContentDocumentLink_Handler {
     //This method restrict .pdf file upload to 'Banking' type account records
     public static void onAfterInsert(list<ContentDocumentLink> lstCntLinks) {
        String strObjPrefix; // to check parent record prefix value like for Account object: 001, for Opportunity: 006 
        Set<Id> setCntDocIds = new set<Id>();
        set<Id> setAgmtIds = new set<Id>();//Store Parent record i.e. Agreement Ids
        map<Id, Account> mapAgmt;
        try{
            for(ContentDocumentLink clIterator : lstCntLinks) {
                strObjPrefix = String.valueOf(clIterator.LinkedEntityId).substring(0, 3); // Return first letters of record id like 001 for Account 
                if(strObjPrefix == Account.sObjectType.getDescribe().getKeyPrefix()) {
                    setCntDocIds.add(clIterator.ContentDocumentId);// Content Document Id
                    setAgmtIds.add(clIterator.LinkedEntityId);// Agreement Id - Parent record Id
                }
            }
            Id recordTypeIdBanking = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Banking').getRecordTypeId();// Account object- 'Banking' Reord Type id
            if(setCntDocIds.size() > 0 && setAgmtIds.size() > 0 ) {           
                mapAgmt = new map<Id, Account>([SELECT Id, Name,RecordTypeId FROM Account WHERE Id IN :setAgmtIds and RecordTypeId = :recordTypeIdBanking]);
                //Fetching parent record details and restricting only if Record type is Account 
                if(mapAgmt.size() > 0){
                    map<Id, ContentDocument> mapContentDocuments = new map<Id, ContentDocument>([SELECT Id, Title, FileExtension FROM ContentDocument WHERE Id IN :setCntDocIds]);
                    list<ContentDocument> lstCntDocsToUpdate = new list<ContentDocument>();        
                    for(ContentDocumentLink cdlIterator : lstCntLinks) {
                        ContentDocument objCntDoc = mapContentDocuments.get(cdlIterator.ContentDocumentId);
                        // Allow all files except : pdf 
                        if(objCntDoc.FileExtension == 'pdf'){
                            cdlIterator.addError('You can not upload pdf files for Banking type accounts.');//Showing error   
                            // This line will abort file upload option. 
                            // Error message will be displayed only when 'ContentDocumentLink' object has some RecordType created (any other than Master)
                            // else Generic message will be dispayed - 'Can not add 1 file to Account'.   
                        }                        
                    }  
                }
            }
        }
        Catch (Exception ex){
            system.debug('Exception in TW_ContentDocumentLink_Handler class :' + ex.getMessage());
        }
    }
}

*********************************************************************************


Follow me @LinkedIn - sud-gupta

Keep Learning ... Keep Growing !!!

Saturday, 25 April 2020

Create formula field image button with lightning style in SalesForce and add it to page layout

For some requirements, we need to create a formula field image button (hyperlink) that redirects to a link (like record details page, external website, VF page, Lightning app page) and pass parameters like Id, Stage Name, Status etc.


Formula Field Button with Lightning UI


Here I'll show you:

  1. How to create an image button that looks like a lightning button using  MS Paint.
  2. Upload this image button in the static resources.
  3. Create a formula field and use the previously created image button.
  4. Add button to Page Layout
  5. On click of this button how to redirect to a Visual Force page/record detail page/ external link   
Quick demonstration:




STEP 1: Create an image button using paint 
Note: Here we are not creating button image by taking the screenshot of any customized button as it can result in a blur or nonclear image.

Open microsoft paint (Windows have it my default) > File > Properties > Change the height of canvas as  [x] * 29 > do following configurations:

  1. Font-family:  Arial 
  2. Font size: 6 px (you have to type 6 in size window)
  3. Font color:  Red- 69, Green- 105, Blue 150 (Click on 'Edit Colors' button available in top menu section of paint to select this custom color or watch the video for more details)
  4. Border color: Red- 213, Green- 209, Blue 208
  5. Enter button text 
  6. Zoom the Paint canvas to 400% > maintain a gap of 8mm between left and right side > keep text at the center. (At the end of this blog, I have attached a sample button, do check it for left and right gap spacing measurement as it may vary based on your machine screen size)
  7. Select font color as border color then using rectangle shape draw border.
  8. Save the image.   

How to use custom color in Paint


STEP 2: Upload image to static resource in Salesforce

Setup > search for 'Static Resource' > Create new > Give meaningful name > Upload button image > copy 'Name' field to note pad for further use


Note: If we need to make any changes in image and we upload that image again then in order to see changes, we need to clear our browser cache.

 STEP 3: Create a formula field 

Set up > Object Manager > Opportunity (or any other object) > Fields and Relationships > New > Select 'Formula Field' > click Next > Enter Field Label and Name > Select Return Type as 'Text'


   In Advance tab > Enter the formula as mentioned below (modify as per your requirement)
IF(ISPICKVAL(StageName, "Qualification") , HYPERLINK('/apex/SendOpportunityForApproval?id=' & Id, IMAGE("/resource/Send_for_management_approval", "Send for Management Approval"), "_blank"), NULL)

How it is working?: It first checks, if the Opportunity stage is 'Qualification', If true then Hyperlink will be displayed. Hyperlink is redirecting to a VF page and passing current record ID as a query string parameter and displaying link as a clickable image.

Note:

  • 'SendOpportunityForApproval' is visual force page name. Replace it with your VF page name.
  • Use "_self", if you want to open link in same page 
  • We can add multiple conditions in IF using AND/OR
  • We can redirect to any link other than VF page like external website, App page, community page etc.
  • We can pass object fields as an additional parameter separated by '&'   



 STEP 4: Add formula field (image button) to the page layout

Set up > Object Manager > Opportunity (or any other object) > Page Layout > Edit >
Drap formula field to the layout 


    
 STEP 5: Click on the button 

 


Sample button image for reference



Follow me @LinkedIn - sud-gupta

Keep Learning ... Keep Growing !!!

Thursday, 23 April 2020

SalesForce data collection Part 1 - LIST

This blog is helpful for SFDC developers or admins to understand SalesForce data collection variable - LIST. It explains all basics and mostly used operations on LIST.  

Every programming language (like C, C++, python, apex) has

  1. Primitive data types like String, Integer etc.
  2. Collection variables like an array.
Apex (Salesforce programming language) has the following data collection (that can store multiple numbers of records) variables:

  1. List (ordered)
  2. Set (unique values and un-ordered)
  3. Map (key-value pair) 

LIST: 

An ordered collection of elements, which is identified by their index. A list can contain any number of records of primitive, collections, sObjects, user defined and built in Apex type.


Example to get the basic idea about LIST

Requirement 1: Store name of class topper
String topperName = 'Sudhanshu'; // Storing single value
Requirement 2: store names of all class students
List<String> studentsName = new List<String>{'Sudhanshu','Sachin','Gaurav','Mariya','Amit'}; // storing collection of string.

Here in requirement example 2, students' names are saved in the list in an ordered way like the index of 'Sudhanshu' is 0, 'Sachin' is 1, and so on. 


How to declare a List?

1. List<String> colorsList = new List<String>(); // Creates a new instance of SET which can hold some value.
2. List<String> colors = new List<String>{'Yellow','Red','Green'}; // with default values
3. List<Integer> rollNumber = new List<Integer>{2,5,7}; // with default value - integer
3.   List<Account> accList = new list<Account>(); // list of type account.
4. List<Account> accList = [Select Id, Name, Industry, Type From ACCOUNT where Industry = 'Utilities'];

Below is an incorrect way of getting account records. It can throw an error if zero records are returned by the SOQL query and we try to do some operation on 'acc' variable.
Account acc = [Select id, Name from accountwhere Industry = 'Utilities'];// Incorrect way

Mostly used methods /functions of  LIST

1. List Null check

Note: List must be initialized before applying a null check.
List<String> colorsList = new List<String>{'Yellow','Red','Green'};
if (colorsList.size() > 0){
   // Do something
}
if (!isEmpty()){
   // Do something
}
List null check
List null check
















Logs Output:
List null check output













2. Looping and sorting values in a List

Use list.sort(); for sorting elements in ascending order
List<String> studentsName = new List<String>{'Sudhanshu', 'Sachin','Gaurav','Mariya','Amit'};
for( String sName : studentsName){
    system.debug('Student Name: ' + sName);
}
studentsName.sort();// Sorting in ascending order
for(String sName : studentsName){
    system.debug('Student Name after sorting: ' + sName);
}
Output














3. Adding an element to a List.

1. list.add(element): adds a single element to a list
2. list.addAll(another list): add contents of an already existing List to a List.
3. list.add(index, element): add element at a specific index 
List<String> studentsName = new List<String>();
studentsName.add('Sudhanshu');
studentsName.add('Sachin');

List<String> studentslist2 = new List<String>();

studentslist2.add('Gaurav');
studentslist2.add('Mariya');
studentsName.addAll(studentslist2);// Addting existing list
studentsName.add(1,'Amit');// adding element at a specific index
system.debug('size of studentsName list: ' + studentsName.size());

for( String sName : studentsName){

    system.debug('Student Name: ' + sName);
}

Log Output:

List: Add element logs output

















4. Converting a String into a List, check if any element exists or not, Converting a list to string

When we query multi picklist field value from an object it returns a string separated by ';' semi comma. If we need to apply some conditions or sorting or any manipulation then we can directly convert a string  to a List.

String cities = 'Mumbai;Pune;Gurgaon;Noida;New York;Toronto';// multi picklist field value or semi comma separated values in a string

List<String> citiesList = cities.split(';');
system.debug( 'size: ' + citiesList.size());// Output - Size: 6
citiesList.sort();
boolean flag = citiesList.contains('Pune');
system.debug( 'flag: ' + flag);//output- true
string x = citiesList.toString();

system.debug('X: ' + x); //output- (Gurgaon, Mumbai, New York, Noida, Pune, Toronto)
   
Contains(): is used to check if  any element is present in List or not
ToString(): is used to convert List values directly into a ',' comma-separated string. 


5. Clear all values in List


Clear: removes all the values from a List.

Example: citiesList.clear();


6. Referring the first element of List returned by SOQL query

List<Account> accList = [Select Id, Name, Industry, Type From ACCOUNT where Industry = 'Utilities' Limit 1];
String accName  = accList[0].Name; // Getting field value


7. Get Index of an element and Get element value by Index

List<String> myStrings = new List<String>{'a', 'b', 'a'};
String myVal = myStrings.get(0);
System.debug('myVal :' + myVal); // output - a
Integer indexValue = myStrings.indexOf('a'); 
System.debug('indexValue of a: ' + indexValue);// output - 0



For all other methods about LIST, refer apex developer guide - link


Keep Learning... Keep Growing !!!   - Sudhanshu Gupta 

LWC Component Bundle | Build your first component | Core Concepts

In my previous blog , I explained all the pre-requisite steps to set up the LWC development environment on your system. Now I'll expl...