Tuesday, December 31, 2019

How To Open Visual Force Page From LWC Components

Please use below code snippet to open the visual force page from LWC.

import { LightningElement,api,track,wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';

export default class CallPopup extends NavigationMixin(LightningElement)
{
    //Call this method from your .html file
 openVisualForcePage(event) 
 {

  const urlWithParameters = '/apex/YourVisualPageName?prop1=propval';
  console.log('urlWithParameters...'+urlWithParameters);
  this[NavigationMixin.Navigate]({
  type: 'standard__webPage',
  attributes: {
  url: urlWithParameters
  }
  }, false); //if you set true this will opens the new url in same window
 }
}

Hope this helps you..Enjoy..!

typeAttributes in lightning-datatable or lightning:datatable

Basically typeAttributes are the one of the major building blocks of <lightning-datatable>(in LWC) or <lightning:datatable> (in Aura).This will help us to format the data types /output display and attaching some of actions to your data displayed in table at each cell level ,row level or at the columns level.

The typeAttributes are attached to each columns data type when your specifying the columns for your data table in your java script file.

Each typeAttributes is having pre-defined set of attributes/properties basis on the data type of your column (your defining at the time of columns for table).

Usually each column definition will have below properties.

{ 
  label: 'Issue Type',  //Column Header Shown in Table
  fieldName: 'Issue_type__c', //Api name of filed 
  type:"text",   // tells text,date,url,email etc..
  initialWidth: 90 //column width
}

After attaching the typeAttributes the sample code looks like below.The sample code will create a column with name Case Number and Looks like a button ,on click of it you can fire rowAction automatically.


{
        label: 'Case Number',
        type: 'button',
        initialWidth: 90,
        typeAttributes: {
            iconName: 'action:preview',
            title: 'Preview',
            variant: 'border-filled',
            alternativeText: 'View',
            disabled: false,
            label: { fieldName: 'CaseNumber' }, // to assign the value dynamically
            name: { fieldName: 'Case_Age__c' }, // to assign the value dynamically
        }
    },

//other colums

At any time if you want to set any of the typeAttribute object attribute dynamically please use below syntax


  attributeName: { fieldName: 'api name of column/any other variable' }
          

As I have mentioned on the top each typeAttributes will have some set of properties based on the data type of your column.

If you want to know what are the available attributes for each datatype please refer below.




Sample Column Code With typeAttributes:


const datatableColums =[
 //Column 1 of type Url
    {
        label: 'Customer Name', fieldName: 'nameUrl', type: 'url',
        typeAttributes: {
            label: { fieldName: 'Name' },
            target: '_top'
        }
    },
 
 //Column 2 of type button 
 {
        label: 'PNR',
        type: 'button',
        initialWidth: 90,
        typeAttributes: {
            iconName: 'action:preview',
            title: 'Preview',
            variant: 'border-filled',
            alternativeText: 'View',
            disabled: false,
            label: { fieldName: 'Pnr__c' },
            name: { fieldName: 'Pnr__c' },

        }
    },
 
 //Column 3 of type date 
 {
        label: "Closed Date",
        fieldName: "ClosedDate",
        type: "date",
        typeAttributes:{
            weekday: "long",
            year: "numeric",
            month: "long",
            day: "2-digit"
        }
    }
]

Please watch this space more useful stuff.

Please follow,bookmark,subscribe this site to receive daily updates.

Facebook - https://www.facebook.com/ILoveCodingYou/?ref=bookmarks


Hope this helps you..Enjoy..!






How To Build A Global Search URL In Lightning Experience Using JavaScript

If your in lightning experience on click of any actionable item you want to take the user to the Global Search and perform the search action using the dynamic search string.To get the url of the global search in lightning using java script please refer the below code.


var searchStr = 'Sree'; //Search String
var stringToEncode = '{"componentDef":"forceSearch:search","attributes":{"term":"'+searchStr+ '","scopeMap":{"type":"TOP_RESULTS"},"context":{"disableSpellCorrection":false,"SEARCH_ACTIVITY":{"term":"'+ searchStr + '"}}}}';
var encodedStr = btoa(stringToEncode); //Base64 encoding
var redirectUrl='/one/one.app?source=aloha#'+encodedStr;

The format of url must be

     String redUrl = '/one/one.app?source=aloha#'+base64EncodedSearchString;

If you want to the same thing using apex please refer this post

Hope this helps you..Enjoy..!

How To Build A Global Search URL In Lightning Experience Using Apex

If your in lightning experience on click of any actionable item you want to take the user to the Global Search and perform the search action using the dynamic search string.To get the url of the global search in lightning using apex please refer the below code.


String searchStr = 'Sree'; //Search String
String stringToEncode = '{"componentDef":"forceSearch:search","attributes":{"term":"'+searchStr+ '","scopeMap":{"type":"TOP_RESULTS"},"context":{"disableSpellCorrection":false,"SEARCH_ACTIVITY":{"term":"'+ searchStr + '"}}}}';
String encodedStr = EncodingUtil.base64Encode(Blob.valueOf(stringToEncode)); //Base64 encoding
String redirectUrl='/one/one.app?source=aloha#'+encodedStr;

The format of url must be

     String redUrl = '/one/one.app?source=aloha#'+base64EncodedSearchString;

If you want to the same thing using java script please refer this post


Hope this helps you..Enjoy..!




Sunday, December 29, 2019

Salesforce Integration - Latest Interview Questions With Answers

1.What is meant by Integration or Web Services?

In simple terms integration is nothing but exchange/transfer of data between two different applications/systems.This basically provides communication between two applications.These two applications could be of using same technology or it could be of different technology.

Examples :
  • The data exchange between 2 different Salesforce Orgs.
  • The data between Salesforce or Java,.Net or SAP(External services).
The exchange of data happens over internet (Web) so this is termed as Web Services.



2.What is meant by API or Service?

API stands for Application Programming Interface.It is protocol through which one application communicate with other. Salesforce can integrate with third party application and communicate data with API.

In simple terms API is nothing but a class which will take some inputs from the users and returns some response basis on the requirement.The classes which has build for integration purpose can be called as the "Services"

3. What are the popular types of Web Services Protocols available in market?

Below are the two popular Web Services protocol for creating any integration
  • SOAP - Simple Object Access Protocol
  • REST - Representational state transfer
  • Bayeux
Each protocol will have it's own constrains to create any web services.

4. What are the different API's available in Salesforce Eco System?

Salesforce supports wide range of API's so that any external system can interact with Salesforce ecosystem very easily basis on requirement.
  • Bulk Data Processing
  • Tool API's
  • For Building Custom API


For more information please refer

5.What is the difference between REST API and APEX REST API?

Similar to Standard object/fields and Custom object/fields in Salesforce,these APIs are also comes under this Standard APIs and Custom APIs.

REST API: 
This api provided by Salesforce with pre-built set of services which will be running on REST protocol to interact with Salesforce ecosystem.This provides powerful and convenient way to interact with Salesforce system.

This is very easy for integration and it best suits for applications which are running on mobile applications and web projects.The detailed document can be found here.

APEX REST API:

If you have an use case where you want to share some of your salesforce org data with external systems/you want to update salesforce data basis on the external system request with REST protocol and your use case is not available in standard REST API provided by salesforce. 

In these scenarios you will create an apex class which can handle all your scenarios and shares/update the necessary data with external systems at the same time running these apex classes on REST protocol.The entire class or methods which has written then exposed with external systems using this APEX REST API.

The detailed document can be found here

6.What are the Authentication mechanisms used by Apex REST API?
  • OAuth 2.0
  • Session Id
7. What is Callout?

When your making an api call to external system from salesforce we will call it as Callout(because the call is going out from salesforce)

8. Is there any difference between contract details,api details or service details?

There is no difference among all these terms are same.These terms are used to describe about the what is the sample request,sample headers,end point,authentication model and sample response details which can be shared/agreed between two parties for integration.

9.How can you say if i have shown two classes which one is Apex Rest API class and other is normal apex class?

If any class is annotated with @RestResource(urlMapping='/sampleurl') will be treated as Apex Rest API class.

@RestResource(urlMapping='/srinivas4sfdc/getCases/*')
global without sharing class API_Get_Cases
{
  //your code
}


10.What is Remote Site Setting and What is the action of it?

Basically in Remote site settings we will add the external system domain address where Salesforce is going to make a callout for some information.

As soon as you added the domain name to the remote site setting it internally informs the Salesforce ecosystems these are my trusted domain names so you can allow call out to these services from Salesforce.

11.What happens if domain is not added while making a callout from Salesforce to External System?

It's mandatory to add the external system domain names in remote site setting while salesforce making any callout to these services.If not added then salesforce treats all these external systems domain names as not trusted domains .So,callout will not triggered from the salesforce.

12.When an external system is making a call to Salesforce in this case should we add the external System domain name in Remote site setting?

No,it's not required .

13.How will Salesforce authenticates every incoming request?

Every third party request coming into Salesforce will be authenticated by OAuth 2.0,using the OAuth 2.0 third party systems will get the access token first from the salesforce authorization server ,then the access token will be passed as part of every request.

So,Salesforce check whether this token is valid or not,expired or not,if everything if fine then only salesforce processes this request otherwise it will throws an error.

14. What is the default time out an api call out?

120 sec - 2 mins

15. Can we make a callout from Trigger Context(In same transaction)?

No,because when your making a callout to external system we don't know whether you will receive the response immediately or it can take some time and some time these external service might be down as well.

So,if your making a callout in trigger context directly you might goes to the dead lock situation because your trigger is waiting for response from external system but external system is not responding quickly.Just keeping the limits in mind Salesforce doesn't support the callout in same transaction from the trigger context.

16. Can we make a callout from Trigger?If how can we make a callout?

In same transaction execution you can't make a callout but salesforce has provided an workaround solution for this ,by splinting the callout functionality from same transaction context(synchronous) to different transaction context(asynchronous).

Trigger always run on the synchronous mechanism and when you call any method with annotation @future(callout=true) the execution context of this method becomes the asynchronous.So,if you want to make a callout from trigger please place your callout logic inside this method so that the callout context moves into asynchronous and trigger don't wait for the callout response and it continues the execution.

17.Can we make a callout from Trigger without using future method?

No,because in same trigger context you can't make a callout. 

18.What are the Concurrent limits in Salesforce?

If multiple requests are running more than the specified time interval then all those request will be treated under Concurrent limits. Salesforce has broadly divided these limits into 2 categories
  • Concurrent API Request limit
  • Concurrent Callout Request/Apex limit
19.Explain about Concurrent API Request limit?

If salesforce receiving any incoming api request from the external systems and all those api requests which are taking more than 20 sec will be counted under these API Request limits.

At any given point of time salesforce allows only 25 requests running more than 20 sec is allowed.If 25 requests are already took 20 sec and meanwhile if you receive 26th request and if this 26th request is also crossing the 20 sec then system will throws an error an terminates this 26th request automatically.

In case if 26th request is finished it's execution within 20 sec then no error will be thrown.

20. Explain about Concurrent Callout Request/Apex limits?

If salesforce is making any callout to external systems synchronously from visual force,if any callout taking more than 5 sec(long running processes) will be counted under this Concurrent Callout Request limit.

At any given point of time salesforce allows only 10 long running callouts .If already 10 callouts are running and all these taking more than 5 sec,in this case if you receive 11 callout request and if this is also taking more than 5 sec then system automatically terminates this stating concurrent limit exceeded.

21. How can we avoid Concurrent Callout Request/Apex limits?

Yes,we can avoid these errors just moving all these synchronous long running request into asynchronous long running request by using the Continuous Integration.

For more details about this please refer my detail post


Please watch this space more interview questions.

Please follow,bookmark,subscribe this site to receive daily updates.

Facebook - https://www.facebook.com/ILoveCodingYou/?ref=bookmarks

Hope this helps you..Enjoy..!

Continuation Integration In Salesforce

Problem: 

When multiple agents are using same visual force page (User Interface) and we are making an external call out to fetch the data from the back end systems,if the external service is taking more time (more than 5 sec) to respond ,all such transactions will be treated as a long running transactions in salesforce .At at any given point of time salesforce allows only 5 long running processes in system and it automatically terminates the other requests and it will not allow the agents to perform any other actions.

New Approach: 

Our salesforce system is more dependent on other services to provide the necessary data to the agent usually we will end up with same issue many times.So,we have decided to change the existing integration model and for all new integrations we have started using continuation frame work.In this frame work all the external call outs which are taking longer time ,all these long running requests will be converted into asynchronous callout and this will not be counted under the salesforce limits and also it will not stop the agents doing other works.

Usually agent can request for data on click of any button or action in visual force and this will make an external call out (step 1) and the app server will handover the request to continuation server before it returning to the visual force page  (steps 2–3) .The Continuation server sends the request to the Web service and receives the response (steps 4–7), then hands the response back to the app server (step 8). Finally, the response is returned to the Visual force page (step 9).



Hope this helps you..Enjoy..!

Saturday, December 28, 2019

What is Salesforce API Portal?

This is the new feature of Salesforce which will help us to find all api details to connect with any of their platforms/entire ecosystem through apis.

We can also say it's one place store to check out all salesforce api details.

This will also shows what is the sample request and response details for each and every api.

It will also helps the developers to learn with an interactive document.

This helps the developer to connect with entire eco system.

This is built on Mulesoft API Community Manager.

Sample API/Clouds:

  • B2C Commerce Developer Sandbox API's
  • Einstein Prediction Service Scoring API
  • Einstein Vision and Einstein Language
  • Marketing Cloud REST API

For more details please check Salesforce Official Documentation.

Hope this helps you..Enjoy..!



Error: [LWC error]: Invalid event type "WireContextEvent" dispatched in element force-aloha-page

Usually when we are rendering any LWC component in Lightning experiences or Lightning console applications sometimes you will receive this error.

The complete looks like below in your browser console

aura_proddebug.js:4283 Error: [LWC error]: Invalid event type "WireContextEvent" dispatched in element <force-aloha-page>. Event name must 1) Start with a lowercase letter 2) Contain only lowercase letters, numbers, and underscores
<force-aloha-page>
    at Object.logError (aura_proddebug.js:4279)
    at AlohaPage.dispatchEvent (aura_proddebug.js:7633)
    at DomContextBinding.get (contextService.js:106)
    at findContextProvisions (contextService.js:296)
    at getContextProvisions (contextService.js:337)
    at Object.getContextValue (contextService.js:355)
    at getDelegate (pageService.js:7)
    at PageServiceClient.getCurrentPageReference (pageService.js:28)
    at AlohaPage.connectedCallback (alohaPage.js:688)
    at callHook (aura_proddebug.js:8345)
logError @ aura_proddebug.js:4283


According to Salesforce LWC Documentation the LWC components are not completely supported in all the environments,applications and display sections.

So,this error comes when your rendering any LWC component in any of the area where salesforce doesn't support these LWC components.

Solution:

To fix this error please place your LWC component in Aura component then the LWC component will work without any errors.

Notes:

  • This could also comes in the cases where your using any lightning interface or feature which will not support in classic environment then also this comes.
  • In those cases wrapping inside the aura also will not help us.



Hope this helps you..Enjoy..!

Invalid Reference lightning-navigation Of Type Module in file .js Issue in LWC

Usually you will receive this error when your trying to import the navigation package of Salesforce for navigation in LWC.

Error Code:

import { LightningElement,api,track,wire } from 'lwc';
import { NavigationMixin } from 'lightning-navigation';

export default class YourClassName extends NavigationMixin(LightningElement)
{
  // your code
}

If you try to save the class with above code you will receive same error.So,to fix this issue please replace lightning-navigation with lightning/navigation while importing.

Solution:


import { LightningElement,api,track,wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';

export default class YourClassName extends NavigationMixin(LightningElement)
{
  // your code
}

Hope this helps you..Enjoy..!

Monday, December 23, 2019

Batch Apex - Interview Questions With Answers

1. How many active batches(running parallel) can be allowed at a time?

Salesforce by default allows 5 active batches running at a time and other batches will be in queue for running

2. How can we schedule batch class to run in future only once from the specified minutes from current time.

public static String scheduleBatch(Database.Batchable batchable, String jobName, Integer minutesFromNow)

or

public static String scheduleBatch(Database.Batchable batchable, String jobName, Integer minutesFromNow,Integer batchSize)

3.How to calculate the batch size if we are making any call out from the batch class execute method?

Basically in salesforce we have limitation of 100 call outs for a transaction.When it comes to batch class each execute method call will be considered as one transaction.So,in this case your batch size must be calculated in such way

   Batch size = (No of callouts allowed for single transaction /total number of call outs for each record) - 1;

   Batch size = (100 /total number of call outs for each record) - 1;


4. How to stop all the running batches related to a particular batch classes before scheduling the same batch class from the schedule class.


global class CaseCreationonSchedular implements Schedulable
{
    global void execute(SchedulableContext SC)
    {
        
        for(AsyncApexJob ap: [SELECT Id, ApexClass.Name,createddate, JobType, Status, JobItemsProcessed, MethodName, ParentJobId FROM AsyncApexJob Where ParentJobId!=Null AND JobType IN('BatchApex','BatchApexWorker') And ApexClass.Name='YourBatchClassName' And Status NOT IN('Completed','Aborted')])
        {
          System.abortJob(ap.ParentJobId);

        }
        YourBatchClassName cls = new YourBatchClassName();
        DataBase.executeBatch(cls);
    }
}

5.How can we schedule a batch class to run every 10 or 5 or 2 mins.

Salesforce haven't provided wild card entries (* every,- range,/,?) in place of minutes and seconds.So,if you want schedule a class to run every  10 minutes you have to schedule same class 6 times (60min/6) with diff batch name ,for 5 mins 12 times and for 2 mins 30 times..As the time interval keeps going down schedule the same class goes up which is an irritating thing to monitor or even it's very hard to handle these many jobs.

For this we can simply do this in the code so that at any given point of time you will have only schedule job running for the same.


global class CaseCreationonSchedular implements Schedulable
{
    public void execute(SchedulableContext scon)
    {
        System.abortJob(scon.getTriggerId()); // abort already running schedule job 
        Decimal nextInterval = System.Label.nextIntervalTime; // config to decide next interval 2,5 or 10 mins etc..
        System.schedule('CaseCreationonBatch - '+String.valueOf(DateTime.now()), '0 '+DateTime.now().addMinutes(Integer.valueOf(nextInterval)).minute()+' */1 ? * *', this); //Schedule the class to run with specified time
  
        Database.executeBatch(new YourBatchClassName()); // Call you batch class 
       
    }
}

6.Why to use Batch class as we already having data loader to process the bulk data.

Agree with this point if and only if the data needs to be updated is static or predefined or which can be done through excel.

We will choose batch class if we have to perform some custom calculations at run time or if you want to run some complex logic which can't be driven by excel sheets in those cases we have to go with batch classes.

Examples:

  • Do some relationship quires to update the data.
  • Make a call out to get the some information related to each record.
7.How many times the execute method will be executed to process the  1234 records.

It depends on your batch size what you have configured at the time of calling the batch class from schedule class.

Execution method count = Total No Of Records/Batch Size (Any decimal ceil it to upper value)
  • If you haven't set any batch size then - 1234/200 = 6.17 = 7 times execute method will be called

8.What is the maximum size of a batch that we can set up ?

2000

9.What is the minimum batch size we can set up is?

1

10.What is the default size of batch if we haven't configured at the time of execution?

200

11.What is Apex Flex Queue?

At a time salesforce allolws 5 batches to be running or to be in queued state.So,if you have consumed all these 5 limits and if system has received one or more batch execution request all these waiting batch will be stored in this Apex Flex Queue.

12. What is the maximum number of batch classes allowed in Apex Flex Queue for execution?

100

13.How can we do chaining of batch jobs?

we can do this by simply calling the chained batch/second batch class from the finish method of the first batch class.

Why to call only from the finish method why not from execute?because the execute method will gets invoked multiple times based on the volume of the records and batch size.So,if your calling it from execute method then the chaining class will get called multiple times which is not an suggested way of doing.

We can also use the Queueable Apex for chaining of the jobs.


Hope this helps you..Enjoy..!

Sunday, December 22, 2019

How To Select And Update Multiple Records Using LWC

If you have a requirement like to display the list of records related to particular record and then selection option to select one or many records from the display list and update the selected records.

And this entire functionality if you want to do using the LWC please follow the below steps and code.

Example :I'm building a component to display list of cases under a particular account and then I'm providing a button to user to make a call out to check which cases can be closed now.

As soon as I got a response from the api i will display all the cases which can be closed now with check box for selection and other cases with non selection option.

For generic demo purpose I'm assuming by default alternative cases are non-closable. So,to test this feature please select account with at least minimum 3 case records.



Apex Class- CaseFilterinLWCCntrl.cls

/**
 * (c) 2019 - srinivas4sfdc.com 
 *
 * Name           : CaseFilterinLWCCntrl
 * Created Date   : 22 Dec 2019
 * Created By     : Sreenivas M
 * Purpose        : Controller class for CaseFilterLWC component.
 *
 **/

global class CaseFilterinLWCCntrl
{
    
    public static List<Case> listCases{get;set;}  
    public static Id recId{get;set;}
    
    public CaseFilterinLWCCntrl(ApexPages.StandardController controller)
    {
        recId = controller.getId();
    }

    @AuraEnabled(cacheable=true)
    public static List<Case> fetchAllCases(String accntId)
    {
        listCases = new List<Case>();
        listCases = [Select id,casenumber,status,Origin,Subject,Type,ContactMobile FROM Case WHERE AccountId=:accntId limit 20];
        return listCases;
    }
 
 @AuraEnabled
    public static List<CasesWrapper> checkIsCloseableCases(List<Case> listAllCases)
    {
        
        System.debug('listAllCases...'+listAllCases);
        String errMsg ='';
        List<String> listCaseNum =new List<String>();
        List<String> listCloseableCaseNum =new List<String>();
        String respString = '{"cases":["';
        
        for(Integer i=0;i<listAllCases.size();i++)
        {
            listCaseNum.add(listAllCases[i].casenumber);
            if(Math.mod((i+1),2) == 0)
                listCloseableCaseNum.add(listAllCases[i].casenumber);
        
        }
        
        String finalCaseClose = String.join(listCloseableCaseNum,'","');
        respString = respString+finalCaseClose +'"]}';
       
        String jsonBody = '{"Country":"IND","casenumber":["'+finalCaseClose+'"]}';
        
        System.debug('respString ...'+respString +'...'+jsonBody);
        Http http = new Http();
        HttpResponse res = new HttpResponse();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('endPoint details..');
        req.setMethod('POST');
        req.setBody(jsonBody);
        req.setHeader('Content-Type', 'application/json');
        req.setHeader('Currency', 'INR');
       
        try
        {
          //  res = http.send(req);                      
            string responseValue;// = res.getBody();           
         //   system.debug('responseValue-->>'+responseValue+''+res.getbody());
            responseValue = respString;           
         
                
            if(String.isNotBlank(responseValue)) //   if(res.getStatus()=='OK' && res.getStatusCode()==200 && String.isNotBlank(responseValue))
            {
                 map<string,object> IsCan = (map<string,object>)JSON.deserializeUntyped(responseValue);
                 List<CasesWrapper> listcaseWrap = new List<CasesWrapper>();
                 System.debug('responseValue...'+responseValue);
                 if(IsCan!=null && IsCan.containsKey('cases'))
                 {
                   List<String> closeableCsNum =new List<String>();
                   for(Object obj: (List<Object>)IsCan.get('cases'))
                       closeableCsNum.add((String)obj);
                   
                     System.debug('closeableCsNum...'+closeableCsNum);
                   for(Case cs : listAllCases)
                   {
                       if(closeableCsNum.contains(cs.casenumber))
                           listcaseWrap.add(new CasesWrapper(cs,true));
                       else
                            listcaseWrap.add(new CasesWrapper(cs,false));
                   }
                   
                   System.debug('listcaseWrap....'+listcaseWrap);
                   return listcaseWrap;
                 }
                 
                 else
                 {
                    errMsg ='Received invalid response';
                    throw new AuraHandledException(errMsg); 
                 }
            }
            else
            {
                    errMsg ='Oops something went wrong';
                    throw new AuraHandledException(errMsg); 
            }
        }
        
        Catch(Exception e)
        {
            System.debug('Exception ---'+errMsg);
            AuraHandledException ex = new AuraHandledException(errMsg);
            ex.setMessage(errMsg);
            throw ex;          
        }
    }
    
    @AuraEnabled
    public static string closeSelCases(List<String> listSelCasesToUpdate)
    {
        List<Case> listCasesToUpdate = new List<Case>();
        for(Case cs : [Select id,Status From Case WHERE CaseNumber IN :listSelCasesToUpdate])
        {
        //  cs.Status = 'Closed';
          listCasesToUpdate.add(cs);
        }
        
        try
        {
            if(!listCasesToUpdate.isEmpty())
            {
                update listCasesToUpdate;
                return 'Selected Cases Has Been Closed Successfully';
             }
         }
         Catch(Exception e)
         {
            AuraHandledException ex = new AuraHandledException(String.valueOf(e));
            ex.setMessage('An Error Occured While Closing The Cases');
            throw ex; 
         }         
          
        return null;
    }
       
                    
    public class CasesWrapper
    {
        @AuraEnabled public Case cs{get;set;}
        @AuraEnabled public boolean isCloseable{get;set;}
        @AuraEnabled public Boolean isSelect{get;set;}
            
        public CasesWrapper(Case csObj,Boolean closeable)
        {
            this.cs = csObj;
            this.isCloseable = closeable;
            this.isSelect = false;
        }

    }
 }

updateListOfCases.js (Java script controller of LWC):


/* eslint-disable no-script-url */
/* eslint-disable no-undef */
/* eslint-disable vars-on-top */
/* eslint-disable no-console */
/* eslint-disable no-unused-vars */
import { LightningElement, api, track, wire } from "lwc";
import fetchCases from "@salesforce/apex/CaseFilterinLWCCntrl.fetchAllCases";
import checkIsCloseableStatus from "@salesforce/apex/CaseFilterinLWCCntrl.checkIsCloseableCases";
import closelSelected from "@salesforce/apex/CaseFilterinLWCCntrl.closeSelCases";

const allCasescolumns = [
    {
        label: 'Case Number', fieldName: 'nameUrl', type: 'url',
        typeAttributes: {
            label: { fieldName: 'CaseNumber' },
            target: '_top'
        }
    },
    { label: 'Status', fieldName: 'Status' },
    { label: 'Origin', fieldName: 'Origin' },
    { label: 'Subject', fieldName: 'Subject' },
    { label: 'Type', fieldName: 'Type' },
    { label: 'ContactMobile', fieldName: 'ContactMobile', type: 'text' }

];

export default class UpdateListOfCases extends LightningElement {
    @api recordId;
    @track listAllCases;
    @track listAllCloseableCasesData;
    @track listcancelSeltedCases = [];
    @track columns = allCasescolumns;
    @track showDefTable;
    @track showIsCloseableBtn;
    @track showConfirmClosebtn;
    @track totalNoOfCases;
    @track showErrMsg;
    @track notifType;
    @track notifMsg;
    @track isLoading;

    @wire(fetchCases, { accntId: '$recordId'})
    wiredFetchCasesList({ error, data }) {
        if (data) {
            this.showIsCloseableBtn = true;
            this.listAllCases = data.map(record => Object.assign(
                { "nameUrl": '/console#%2F' + record.Id },
                record));

            this.totalNoOfCases = this.listAllCases.length;
            this.showDefTable = true;
        }
        else if (error) {
            this.error = error;
            this.listAllCases = undefined;
            this.showIsCloseableBtn = false;
        }
    }

    checkIsCloseableCasesJs(event) {
        this.isLoading = true;
        this.showDefTable = false;
        this.showIsCloseableBtn = true;
        this.showErrMsg = false;
        console.log('this.listAllCases....' + this.listAllCases);
        checkIsCloseableStatus({ listAllCases: this.listAllCases })
            .then(result => {
                this.listAllCloseableCasesData = result;
                this.showIsCloseableBtn = false;
                this.showConfirmClosebtn = false;
                this.isLoading = false;

            })
            .catch(error => {

                var errorMsg;
                if (Array.isArray(error.body)) {
                    this.errorMsg = error.body.map(e => e.message).join(', ');
                } else if (typeof error.body.message === 'string') {
                    this.errorMsg = error.body.message;
                }
                console.log('proper error--->' + this.errorMsg);
                this.isLoading = false;
                this.showErrMsg = true;
                this.notifType = 'error'; 
                this.notifMsg = this.errorMsg;
            });

    }

    rowSelChangeEvent(event) {
        this.showConfirmClosebtn = false;
        this.listAllCloseableCasesData.forEach(element => {
            if (element.cs.CaseNumber === event.currentTarget.dataset.id) {
                element.isSelect = event.target.checked;
            }

        });

        for (let i = 0; i < this.listAllCloseableCasesData.length; i++) {

            if (this.listAllCloseableCasesData[i].isSelect) {
                this.listcancelSeltedCases.push(this.listAllCloseableCasesData[i].cs.CaseNumber);
                this.showConfirmClosebtn = true;
            }

        }

    }

    selectDeselectAll(event) {
        if (event.target.checked) {
            this.listAllCloseableCasesData.forEach(element => {
                if (element.isCloseable) {
                    element.isSelect = true;
                    this.showConfirmClosebtn = true;
                }

            });
        }
        else {
            this.listAllCloseableCasesData.forEach(element => {
                if (element.isCloseable) {
                    element.isSelect = false;
                }
                this.showConfirmClosebtn = false;
            });
        }

    }

    closelselectedCaseJs(event) {
        this.isLoading = true;
        this.showErrMsg = false;
        this.listcancelSeltedCases = [];

        for (let i = 0; i < this.listAllCloseableCasesData.length; i++) {
            if (this.listAllCloseableCasesData[i].isSelect) {
                this.listcancelSeltedCases.push(this.listAllCloseableCasesData[i].cs.CaseNumber);
            }
        }


        closelSelected({ listSelCasesToUpdate: this.listcancelSeltedCases })
            .then(result => {
                console.log('cases--->' + result);
                this.showConfirmClosebtn = false;
                this.showErrMsg = true;
                this.notifType = 'success';
                this.notifMsg = result;
                this.isLoading = false;

            })
            .catch(error => {

                var errorMsg;
                if (Array.isArray(error.body)) {
                    this.errorMsg = error.body.map(e => e.message).join(', ');
                } else if (typeof error.body.message === 'string') {
                    this.errorMsg = error.body.message;
                }

                this.showConfirmClosebtn = true;
                this.showErrMsg = true;
                this.notifType = 'error';
                this.notifMsg = this.errorMsg;
                this.isLoading = false;

            });

    }

}

updateListOfCases.html

<template>
   <!-- To show the toast message in vf pages/classic enviornment-->
    <template if:true={showErrMsg}>
        <c-generic-toast-messages notificationtype={notifType} notificationmessage={notifMsg}></c-generic-toast-messages>
        <div class="slds-m-bottom_x-small"></div>
    </template>



    <template if:true={showDefTable}>
        <lightning-datatable data={listAllCases} columns={columns} key-field="id" hide-checkbox-column="true"></lightning-datatable>
    </template>


    <template if:true={listAllCloseableCasesData}>

        <div>
            <table class="slds-table slds-table_cell-buffer slds-table_bordered">
                <thead>
                    <tr>
                        <th>
                            <lightning-input type="checkbox" label="" onchange={selectDeselectAll} value={selAllChe}>
                            </lightning-input>
                        </th>
                        <th>Case Number</th>
                        <th>Status</th>
                        <th>Origin</th>
                        <th>Type</th>
                        <th>Subject</th>
                        <th>ContactMobile</th>
                        <th>Can Close?</th>
                    </tr>
                </thead>
                <tbody>
                    <template for:each={listAllCloseableCasesData} for:item="aItem">
                        <tr key={aItem.cs.CaseNumber}>
                            <td>
                                <template if:true={aItem.isCloseable} class="slds-text-align--left">
                                    <lightning-input type="checkbox" data-id={aItem.cs.CaseNumber} label="" value={aItem.isSelect} checked={aItem.isSelect} onchange={rowSelChangeEvent} ></lightning-input>
                                    <span class="slds-checkbox--faux"></span>
                                    <span class="slds-form-element__label text"></span>
                                </template>
                                <template if:false={aItem.isCloseable}>
                                    <lightning-icon icon-name="utility:error" alternative-text="Can't Close" variant="error" size="x-small" style="padding:0.1rem !important;"></lightning-icon></span>
                                </template>

                            </td>
                            <td >{aItem.cs.CaseNumber}-{aItem.isCloseable}</td>
                            <td >{aItem.cs.Status}</td>
                            <td>{aItem.cs.Origin}</td>
                            <td>{aItem.cs.Type}</td>
                            <td>{aItem.cs.Subject}</td>
                            <td>{aItem.cs.ContactMobile}</td>                          
                            <td class="slds-text-align--center">
                                <template if:true={aItem.isCloseable}>
                                    <lightning-icon icon-name="action:approval" alternative-text="Closeable" size="xx-small" style="padding:0.1rem !important;"></lightning-icon>
                                </template>
                                <template if:false={aItem.isCloseable}>
                                    <lightning-icon icon-name="utility:error" alternative-text="Non-Cancellable" variant="error" size="small" style="padding:0.1rem !important;"></lightning-icon>
                                </template>
                            </td>
                          
                        </tr>
                    </template>

                </tbody>

            </table>
        </div>
    </template>
    <template if:true={showIsCloseableBtn} class="slds-is-relative">
        <lightning-button label="Check Closeable Cases" title="Check Closeable Cases" variant="success" onclick={checkIsCloseableCasesJs} class="slds-align_absolute-center slds-m-top_medium slds-size_small"></lightning-button>

        <div if:true={isLoading}>
            <lightning-spinner alternative-text="Loading..." variant="brand" size="large" class="slds-is-absolute"></lightning-spinner>
        </div>
    </template>


    <template if:true={showConfirmClosebtn} class="slds-is-relative">
        <lightning-button label="Close Selected" title="Close Selected" variant="success" onclick={closelselectedCaseJs} class="slds-align_absolute-center slds-m-top_medium"></lightning-button>
        <div if:true={isLoading}>
            <lightning-spinner alternative-text="Loading..." variant="brand" size="large" class="slds-is-absolute"></lightning-spinner>
        </div>
    </template>

    <template if:false={listAllCases}>
        No Cases Found For This Account.
    </template>
</template>

updateListOfCases.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="updateListOfCases">
    <apiVersion>46.0</apiVersion>
    <isExposed>true</isExposed>
     <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

After deploying all these changes we are ready to go demo and below is the sample demo how this code works.


Please keep below points as notes while developing the same.
  • { "nameUrl": '/console#%2F' + record.Id } - This is to open a record in classic console using lightning out
  • <c-generic-toast-messages> - Custom component used to show toast messages in classic environment,in case of lightning we can directly use toast messages.
For more update please like/follow this page on

Hope this helps you..Enjoy..!