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 !!!

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...