Saturday, June 20, 2020

How to do Callout from Lightning web components

Hello Friends,

Today we are going to disscuss ,how to do Callout from Lightning web components.we can do callout by two way

  1) Call apex Class from LWC and from apex class call REST or SOAP API(Server Side)
`2) Call REST or SOAP Api from LWC component controllert .(Client Side)

Calling REST or SOAP Api from LWC ,we can do my The Fetch API provides a JavaScript interface for accessing and manipulating parts of the HTTP pipelin.

sample code for Fetch Api
fetch('http://example.com/vikas.json')
  .then(response => response.json())
  .then(data => console.log(data));
First,Make sure your endpoint is white-list in Content Security Policies (CSP). This is a major difference between callout from Apex vs Callout from the LWC controller, As in Apex, we need to add RemoteSiteSetting. While in LWC JS Controller CSP trusted site do the work

Steps-Add Endpoint URL in CSP:
From Setup, enter CSP Trusted Sites in the Quick Find box, and then CSP Trusted Sites


Now we will create LWC compoent for Callout

lwcMakeTestCallout.html

<template>
    <lightning-card>
        <h3 slot="title">
            <lightning-icon icon-name="utility:connected_apps" size="small"></lightning-icon>
            Make Callout From Lightning Web Components (LWC)
        </h3>
        <div slot="footer">
                
        </div>
        <div class="slds-p-around_medium lgc-bg">
            <lightning-button label="Get The Joke" onclick={getTheDetails}></lightning-button>
        </div>

        <div class="slds-p-around_medium lgc-bg">
            <lightning-textarea readonly value={receivedMessage} rows="7" style="height:150px;"></lightning-textarea>
        </div>   
    </lightning-card>
</template>


lwcMakeTestCallout.js


import { LightningElement } from 'lwc';

export default class LwcMakeCallout extends LightningElement {
    receivedMessage;
    hasRendered = false;
    
    getTheJoke() {
        const calloutURI = 'https://icanhazdadjoke.com';
        // requires whitelisting of calloutURI in CSP Trusted Sites
        fetch(calloutURI, {
            method: "GET",
            headers: {
                "Accept": "application/json"    //  We can add more paremeter as per our requirement 
              }
        }).then(
            (response) => {
                if (response.ok) {
                    return response.json();
                } 
            }
        ).then(responseJSON => {
            this.receivedMessage = responseJSON.joke;
            console.log(this.receivedMessage);
        });
    }

    renderedCallback() {
        if(this.hasRendered == false) {
            this.getTheJoke();
            this.hasRendered = true;
        }
    }
}


Dynamic Picklist Value in Lightning Web Components

Hello Friends,

we are going to disscuss now,how to use Dynamic Picklist Value in Lightning Web Components with out Apex code.We are using attribute to pass the object and Field name and then the component will display available values. It also filter values based on Record Type.

Here we have used getPicklistValues, getObjectInfo from 'lightning/uiObjectInfoApi' using these we get the object info and picklist details

getObjectInfo provide us details related to Object and Field Metadata. We have used defaultRecordTypeId to get the default value for RecordType.
getPicklistValues supports two required parameter first RecordTypeId and second picklist field name.

Samle Code:


showMyPicklistValue.html

<template>
    <lightning-card>
        <h3 slot="title">
            <lightning-icon icon-name="utility:connected_apps" size="small"></lightning-icon>
            Display Dynamic Picklist in Lightning Web Components
        </h3>
        <div slot="footer">

        </div>
        <lightning-combobox name={fieldLabel} label={fieldLabel} value={value} placeholder={fieldLabel}
            options={options} onchange={handleChange}></lightning-combobox>

        <p>Selected value is: {value}</p>
    </lightning-card>
</template>

showMyPicklistValue.js

import { LightningElement, wire, api, track } from 'lwc';
import { getPicklistValues, getObjectInfo } from 'lightning/uiObjectInfoApi';

export default class ShowPicklistValue extends LightningElement {

    @api objectName = 'Account';
    @api fieldName = 'Industry';
    @track fieldLabel;
    @api recordTypeId;
    @api value;
    @track options;
    apiFieldName;

    @wire(getObjectInfo, { objectApiName: '$objectName' })
    getObjectData({ error, data }) {
        if (data) {
            if (this.recordTypeId == null)
                this.recordTypeId = data.defaultRecordTypeId;
            this.apiFieldName = this.objectName + '.' + this.fieldName;
            this.fieldLabel = data.fields[this.fieldName].label;
            
        } else if (error) {
            // Handle error
            console.log('==============Error  ');
            console.log(error);
        }
    }
    @wire(getPicklistValues, { recordTypeId: '$recordTypeId', fieldApiName: '$apiFieldName' })
    getPicklistValues({ error, data }) {
        if (data) {
            // Map picklist values
            this.options = data.values.map(plValue => {
                return {
                    label: plValue.label,
                    value: plValue.value
                };
            });

        } else if (error) {
            // Handle error
            console.log('==============Error  ' + error);
            console.log(error);
        }
    }

    handleChange(event) {
        this.value = event.detail.value;
    }
}          
OutPut:-



Related Document:-
1)https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_lightning_ui_api_object_info
2)https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_wire_adapters_picklist_values

iterate map in Lightning Web Component (LWC)

Hello Friends ,

Here we are going to discuss how to use map in  Lightning Web Component (LWC) . 

Sample code

lwcMyMapIteration.html

<template>
    <lightning-card>
        <h3 slot="title">
            <lightning-icon icon-name="utility:connected_apps" size="small"></lightning-icon>
            Iterate Map in Lightning Web Components
        </h3>
        <div slot="footer">
                
        </div>
            <table class="slds-table slds-table_bordered slds-table_cell-buffer slds-table_col-bordered slds-table_striped">
                <thead>
                    <tr class="slds-text-title_caps">
                        
                        <th scope="col">
                            <div title="Key">Opportunity Name (Key)</div>
                        </th>
                        <th scope="col">
                            <div title="Value">Account Name (Value)</div>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <template for:each={mapData} for:item="mapKey">
                        <tr key={mapKey.key}>
                            <th scope="col">
                                <div title={mapKey.key}>{mapKey.key}</div>
                            </th>
                            <th scope="col">
                                <div title={mapKey.value}>{mapKey.value}</div>
                            </th>
                        </tr>
                    </template>
                </tbody>
            </table>
    </lightning-card>
</template>

lwcMyMapIteration.js

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

export default class LwcMapIteration extends LightningElement {
    @track mapData= [];

    @wire(fetchMapData)
    wiredResult(result) { 
        if (result.data) {
            //mapData = [];
            var conts = result.data;
            for(var key in conts){
                this.mapData.push({value:conts[key], key:key}); //Here we are creating the array to show on UI.
            }
        }
    }
}

LwcMyMapIterationController.apxc

public with sharing class LwcMapIterationController {
    @AuraEnabled(cacheable=true)
    public static Map < String, String > fetchMapData() {
        Map < String, String > mapOppAccount = new Map < String, String >();
        for(Opportunity opp : [SELECT ID, Account.Name, Name FROm Opportunity LIMIT 15])
         mapOppAccount.put(opp.Name, opp.Account.Name);
        return mapOppAccount;
    }
}

Sunday, June 14, 2020

Apex Design Patterns in Salesforce


This Blog describes how to leverage common Apex Design Patterns to optimize your code and ensure reusability, maintainability and performance.

Common Design Patterns

The following are a list of design patterns, some of which are standard object-oriented patterns in a Force.com context, and some of which are specific Force.com patterns.
  • Singleton - minimizing object instantiation for improved performance and to mitigate impact of governor limits
  • Strategy - defining a family of algorithms, enscapsulating each one and making them interchangeable and selectable at runtime
  • Decorator - extending the functionality of an sObject in Apex
  • Facade - simplifying the execution of classes with complex interfaces (e.g. web service callouts)
  • Composite - treating a group of objects in a similar manner to a single instance of that object
  • Bulk State Transition - efficiently tracking the change of a field value in a trigger and executing functionality based on this change
Singleton:

The Singleton pattern attempts to solve the issue of repeatedly using an object instance, but only wishing to instantiate it 
once within a single transaction context.

Sample Code:-
trigger AccountTrigger on Account (before insert, before update) {
    for(Account record : Trigger.new){
        // Instantiate the record type using the singleton class
        AccountFooRecordType rt = AccountFooRecordType.getInstance();
        ....
    }
}

public class AccountFooRecordType {
    // private static variable referencing the class
    private static AccountFooRecordType instance = null;
    public String id {get;private set;} // the id of the record type

    // The constructor is private and initializes the id of the record type
    private AccountFooRecordType(){
        id = Account.sObjectType.getDescribe()
            .getRecordTypeInfosByName().get('Foo').getRecordTypeId();
    }
    // a static method that returns the instance of the record type
    public static AccountFooRecordType getInstance(){
        // lazy load the record type - only initialize if it doesn't already exist
        if(instance == null) instance = new AccountFooRecordType();
        return instance;
    }
}

The above code demonstrates the following:
  • The getInstance() static method will only instantiate an instance of the class if it doesn't already exist in a     lazy-initialization manner
  • The constructor and the instance variable for the class is private to make sure that it cannot be instantiated     outside of the getInstance() method
  • The class defines a private, static instance of itself that can only be referenced via the getInstance() static method

Strategy:

Defining a family of algorithms, enscapsulating each one and making them interchangeable and selectable at runtime.

Sample Code:

1. Create an interface.

public interface Strategy {

   Integer doOperation(Integer num1, Integer num2);
   
}

2. Create concrete classes implementing the same interface.

public class OperationAdd implements Strategy {

   public Integer doOperation(Integer num1, Integer num2) {
      return num1 + num2;
   }
   
}

public class OperationSubstract implements Strategy {

   public Integer doOperation(Integer num1, Integer num2) {
      return num1 - num2;
   }
   
}

3. Create Context Class.

public class Context {

   private Strategy strategy;

   public Context(Strategy strategy) {
      this.strategy = strategy;
   }

   public Integer executeStrategy(Integer num1, Integer num2) {
      return strategy.doOperation(num1, num2);
   }
   
}

4. Use the Context to see change in behaviour when it changes its Strategy.

      Context context = new Context(new OperationAdd());
      System.debug('10 + 5 = ' + context.executeStrategy(10, 5));

      context = new Context(new OperationSubstract());
      System.debug('10 - 5 = ' + context.executeStrategy(10, 5));

Decorator: Extending the functionality of an sObject in Apex.

Sample Wrapper Class using Apex in Salesforce

Sample Code:

Visualforce Page:

<apex:page controller="Sample" tabStyle="Account">
<apex:form >
<apex:pageMessages />
    <apex:pageBlock id="pg">
        <apex:pageBlockSection >
            <apex:pageBlockTable value="{!listWrapper}" var="a">
                <apex:column >
                    <apex:inputCheckbox value="{!a.checkBool}"/>
                </apex:column>
                <apex:column value="{!a.acct.Name}"/>
                <apex:column value="{!a.acct.Industry}"/>
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:form>
</apex:page>

Apex Controller:

public class Sample {
    public List<WrapperClass> listWrapper {get;set;}
 
    public Sample() {
        List<Account> listAcct = [SELECT Name, Industry FROM Account LIMIT 1000];
     
        if(listAcct.size() > 0) {
            listWrapper = new List<WrapperClass>();
         
            for(Account a : listAcct) {
                listWrapper.add(new WrapperClass(a));
            }
        }
    }
 
    public class WrapperClass {
        public Boolean checkBool {get;set;}
        public Account acct {get;set;}
        public WrapperClass(Account acct) {
            this.acct = acct;
        }      
    }
}




Facade:
Simplifying the execution of classes with complex interfaces (e.g. web service callouts).

Sample Code:

/* Complex parts */

class CPU {
    public void freeze() { ... }
    public void jump(long position) { ... }
    public void execute() { ... }
}

class HardDrive {
    public byte[] read(long lba, int size) { ... }
}

class Memory {
    public void load(long position, byte[] data) { ... }
}

/* Facade */

class ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hd;

    public ComputerFacade() {
        this.processor = new CPU();
        this.ram = new Memory();
        this.hd = new HardDrive();
    }

    public void start() {
        processor.freeze();
        ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
        processor.jump(BOOT_ADDRESS);
        processor.execute();
    }
}

/* Client */

class You {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

Composite:
Treating a group of objects in a similar manner to a single instance of that object. Composite pattern is used where we need to treat a group of objects in similar way as a single object. Composite pattern composes objects in term of a tree structure to represent part as well as whole hierarchy. This type of design pattern comes under structural pattern as this pattern creates a tree structure of group of objects.

Sample Code:

Apex Class:

public class Employee {

   private String name;
   private String dept;
   private Integer salary;
   private List<Employee> subordinates;

   // constructor
   public Employee(String name,String dept, Integer sal) {
      this.name = name;
      this.dept = dept;
      this.salary = sal;
      subordinates = new List < Employee >();
   }

   public void add(Employee e) {
      subordinates.add(e);
   }

   public List<Employee> getSubordinates() {
     return subordinates;
   }

}

Execute the below code to set the hierarchy and view the debug log.
      
      Employee CEO = new Employee('John','CEO', 30000);

      Employee headSales = new Employee('Robert','Head Sales', 20000);

      Employee headMarketing = new Employee('Michel','Head Marketing', 20000);


      Employee clerk1 = new Employee('Laura','Marketing', 10000);
      Employee clerk2 = new Employee('Bob','Marketing', 10000);

      Employee salesExecutive1 = new Employee('Richard','Sales', 10000);
      Employee salesExecutive2 = new Employee('Rob','Sales', 10000);

      CEO.add(headSales);
      CEO.add(headMarketing);

      headSales.add(salesExecutive1);
      headSales.add(salesExecutive2);

      headMarketing.add(clerk1);
      headMarketing.add(clerk2);

      //print all employees of the organization
      System.debug(CEO); 
      
      for ( Employee headEmployee : CEO.getSubordinates() ) {
         System.debug(headEmployee);
         
         for ( Employee employee : headEmployee.getSubordinates() ) {
            System.debug(employee);
         }

      }


Related Link