Deep Clone using Headless Actions in LWC

A headless quick action executes custom code in a Lightning web component. Unlike a screen action, a headless action doesn’t open a modal window. So in short, if you want to do some custom logic via apex to run by click of a quick action button we can use headless actions in LWC.

Below are a few examples/use cases where we can implement headless actions.
1. A custom clone button (With Deep Clone)
2. A custom approval button.
3. Submit data to an external system.
4. Enrich the record with details from an external system etc.

Configure a Component for Quick Actions

To use a Lightning web component as a quick action, define the component’s metadata. Specifically to use an LWC as headless action use the below XML for the meta XML file. Note that the <actiontype is Action for a headless quick action and if you would like to enable the component as a screen popup (regular) include actionType as ScreenAction.

<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="">
   <targetConfig targets="lightning__RecordAction">


Now that we have the setup ready, the custom logic that you need to implement must be provided with the js file of the LWC. The HTML file could be empty with just the template tags.
In your Lightning web component, expose invoke() as a public method. The invoke() method executes every time the quick action is triggered.

import { LightningElement, api } from "lwc";

export default class HeadlessSimple extends LightningElement {
  @api invoke() {
    console.log("This is a headless action.");

Example Scenario

So now if you want to use a deep clone logic from the quick action button the code looks like this.

import { LightningElement, api } from "lwc";
import { ShowToastEvent } from 'lightning/platformShowToastEvent'
import { NavigationMixin } from 'lightning/navigation';
import startDeepClone from '@salesforce/apex/ROR_CloneController.startDeepClone';

export default class Ror_deepcloneaction extends NavigationMixin(LightningElement) {

    @api invoke() {
        this.startToast('Deep Clone!','Starting cloning process...');
        //Call the cloning imperative apex js method
        startDeepClone({recordId: this.recordId})
        .then(result => {
            this.startToast('Deep Clone!','Cloning Process Completed');
         .catch(error => {
            this.startToast('Deep Clone!','An Error occured during cloning'+error);

        let event = new ShowToastEvent({
            title: title,
            message: msg,

            type: 'standard__recordPage',
            attributes: {
                recordId: clonedRecId,
                actionName: 'view',


You can see that on click of the quick action button, the invoke method gets executed, that in turn calls the imperative apex call; does the clone; returns the new clone record’s id and on a successful return from the apex, use an event to alert the user and use NavigationMixin to redirect the user to the cloned record.

Please access the code from the Github repo here.

Aura’s Helper Equivalent in LWC

Back in time when we were creating Lightning components on aura framework, developers were hooked on with the helper methods. We all were told that all the reusable code should go into helper methods. However when we moved to LWC development, with no helper javscript file, where do we put all these reusable code? Let is take a look.

Reusable helpers in LWC

In LWC, we just have one javascript file, so it is necessary to have all the reusable code written within this file. Lets take a quick example of how we can call a method that fires toast message. This method we’ll make generic and try to refer from multiple places. Also I’ve added how to use a pattern matching method as well.

import { LightningElement} from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

export default class MyClass extends LightningElement {
    searchTerm = null;
    //Function for maanging toast messages
    showToast(titleMsg,description,variant) {
        const event = new ShowToastEvent({
            title: titleMsg,
            message: description,
            variant : variant
        let pattern = /^([^0-9]*)$/;
            return true;
        else {
            return false;
    validateParam(searchTerm) {
        let searchTermLen = searchTerm.length;
        if (searchTermLen === 0 || searchTermLen > 3) {
            this.showToast('Error','Search Term from must have minimum 1 and maximum 3 characters', 'error');
        else if (searchTermLen === 1) {
                //Some Logic
            else {
                this.showToast('Error','First Character of Search starts with Number', 'error');
    //The handler that will executed from the click of search button
    handleSearchClick(event) {
            // Do all your logic below

From the above its evident that on handleSearchClick(), we call the validateParam() method. From the validateParam() method we are calling the showToast() method by passing parameters. The showToast() method based on its input parameter will render the toast message on the UI.

‘This’ – The magic word!

The key to call reusable code is the use of ‘this‘ keyword. Functions, in JavaScript, are essentially objects. Like objects they can be assigned to variables, passed to other functions and returned from functions. And much like objects, they have their own properties. One of these properties is ‘this‘.

The value that ‘this‘ stores is the current execution context of the JavaScript program. Thus, when used inside a function this‘s value will change depending on how that function is defined, how it is invoked and the default execution context.

Dynamic Actions – A Low Code Lightning Approach


In Salesforce ecosystem, we all love the word ‘dynamic’ as this brings in a lot of flexibility to the business to reuse anything that is dynamic. Quick Actions in salesforce is a great feature after we were forced to replace the JavaScript buttons when we all migrated from classic to lightning. Let it be the object specific quick actions or be it the global quick actions. Quick actions enable users to do more in Salesforce and in the Salesforce mobile app. With custom quick actions, we can make our users’ navigation and workflow as smooth as possible by giving them convenient access to information that is most important.


Lets dive deeper with a use case. Consider we have a record page for Discount Request object with a quick action that initiates an approval process in a backend system. This action was meant for sales agents with a specific profile. The same layout was being shared with all the agents as well and they were also able to see and click the quick action. Now we have been tackling this with some validation rule on the Lightning component that integrates the approval logic. Alternatively, we were using a different record page for those profiles with and without the quick action. So how do we approach it with minimum component and a low code design?

The Solution

With Dynamic Actions, starting from Summer’20, we can prevent the other set of users not to see that action on their layout even if both set of users use the same layout/record page. So how do we do this? Let us follow the below steps:

  1. Navigate to any record page and choose the highlights panel. Select the option “Enable Dynamic Actions”.
  2. Choose ‘Add Action button’
  3. From the Search field choose your Action.
  4. Add the filter.

I have chosen the quick action to be only visible by the Sales Agent Lead Profile.

With this setup, now we display the quick action only to the Sales Agent Lead Profile The other sales agent profile who share the same record page however does not see the button.

Final Thoughts

With the rise of Citizen Developers and a low code approach across industries and customers, this feature adds a lot of flexibility to reuse the existing layouts and record page without the need to further add more component or to have logic in custom components. One limitation with Dynamic Action is that currently this is supported on record pages for custom objects alone.

Salesforce Database Architecture in a Nutshell

Salesforce database is a topic that is not much discussed between the trailblazers. The reason for this could be that salesforce being a SaaS application, will maintain the database on its own and nobody really bothered to go in detail to understand how the data is stored and how access to that data is controlled. In this guide, you will understand the details of the Database Architecture a little bit in depth to understand where the data is stored and how the data access is provided.

Data Storage is quite easy to understand as salesforce uses Object record table to store the data. However the data access is maintained through a complex multi table setup which we will see as outlined below.

Data Access in salesforce falls into two categories:

  • Object Access
  • Record Level Access

Object Access includes the field level access and is controlled using Profiles and Permission sets. Restricting or Opening Up access to an object is controlled using the CRUD, View All & Modify All permissions.

Record Level access determines which records of an object a user can see and uses the following tools.


Access Grants

When a user demands access to a record, Salesforce doesn’t look at the sharing rule/hierarchies to provide access in real time, rather it calculates record access data and store on group maintenance table whenever a configuration change occurs. This way it provides a quick scanning on these tables to retrieve access data to determine record access at runtime. Such scans happen every time a user tries to access a record on UI, run a report, access list view or access record via API and this makes salesforce so powerful at its access grants. When an object Salesforce uses access grants to define how much access a user or group has to that object’s records. Each access grant gives a specific user or group access to a specific record. It also records the type of sharing tool — sharing rule, team, etc. — used to provide that access. Salesforce uses four types of access grants:


Explicit Grants: Used when records are directly shared to a group or user. This can happen on the below scenarios.

  • Owner of a record
  • Sharing rule that shares a record to a public group, queue, role or a territory
  • Assignment rule shares a record to a user or group.
  • Territory assignment rule.
  • Manual Sharing
  • Account/Opportunity/Case Team
  • Programmatic Sharing (*Previously Apex Sharing)

Group Membership Grants: This type of grant is provided when a user becomes part of a public group, queue, role, or territory.

Inherited Grants: Used when a user inherits access through a role or territory hierarchy or is a member of a group that inherits access through a group hierarchy.

Implicit Grants: Referred as built-in sharing and is non-configurable type of grant. Users can view a parent account record if they have access to its child opportunity, case, or contact record and vice versa.

Database Architecture

Salesforce Stores Access Grants in the below three tables.


Group Maintenance Tables

This table store the data supporting group membership and inherited access grant. The below video will explain how a group maintenance table will be used to provide the required access.

In the video, the scenario being explained has the two roles East Sales Rep & West Sales Rep are at same hierarchy and using sharing rule the records have been shared to each other. This setup a group maintenance table with the group name and users. In this case groups would be system defined groups; which is for the roles.


With the above setup in place in the org, now lets take a look at the video.

Configure Case Deflection Metrics on Community Cloud

Now that you have built your customer community and customers are flowing into the community to view latest products, get help from community members, view knowledge articles etc. In a case to measure the community effectiveness, the community manager wants to generate reports on how well the articles are helping the customers. Community manager wants to see which articles help the customers the most, how many cases were stopped because the customer chose not to create it by seeing an article. To view these metrics, salesforce has a package: ‘Salesforce Case Deflection Reporting Package for Lightning Communities’. Below is the link to the package on AppExchange. This package has dashboard that shows insights into how well the Contact Support Form and Case Deflection components actually deflect cases from being created in your Lightning communities.

How does this work?

The contact support form component that creates the case record is placed in the lightning community along with the case deflection component. The ‘Case Deflection Component‘ searches text as it’s being entered into the Contact Support Form component and returns relevant articles and discussions. If users don’t get the answer they need, they can continue with their request for support. This lightningcommunity:deflectionSignal (system event) is fired in a Lightning community when a user is deflected away from creating a customer case. After viewing an article or discussion in a community, the user is asked if the interaction was helpful, and whether they want to stop creating their case.

Let us now look at the below video to understand how we can setup a community using the case deflection metrics. For the purpose of the demo, I will show just one deflection, hence the report and dashboards may not look really great. But it will definitely serve the purpose to understand how to setup case deflection metrics. Lets see what are the essential components that is required to be added to the community.

Quick Demo

Spring’ 20 Feature – Upgrades to Change Set

Changesets are salesforce’s native way of transferring customization/configuration from one org to another. Change sets can contain only modifications you can make through the Setup menu- which are supported by the metadata. You can’t deploy data (For e, g: List of contacts). Change sets contain information about the org. They don’t contain data, such as records.

Faster availability of uploaded changeset

In salesforce the changeset that we create from the source sandboxes are called the outbound changeset and the target org that receives the changesets are called inbound changeset. During many times there have been issues with the upload and receive of the changeset as it takes considerable time to see the uploaded changeset in your target org. With the onset of Spring ’20 salesforce has optimized the way changesets are uploaded and received. Now, uploaded change sets are available for deployment sooner. Salesforce has not provided any metrics for this improvement. So, lets see how this make a difference. Please do comment if you have noticed improvements.

New Metadata for changeset

Following are the new components that are available from Spring ’20 release that can be included in the changeset. All these are also available to use with ANT based or sfdx mdapi commands.

Component NameMetadata API NameWildcard Support
Email ServiceEmailServicesFunctionNo
Lightning Community TemplateCommunityTemplateDefinitionYES
Lightning Community ThemeCommunityThemeDefinitionYES
Lightning Message ChannelLightningMessageChannel YES
Managed Content TypeManagedContentTypeYES
Whitelisted URL for RedirectsRedirectWhitelistUrlYES


As most of the project are moving away from changeset and with the reception of ANT and sfdx, let’s wait and see how often we see improvements to the changeset way of deployment.

Authenticate SFDX using JWT

Being late into understanding SFDX, I wasn’t sure what were its capabilities and on a normal development project, I don’t think there is enough opportunity to work with SFDX. Luckily, I got a chance to work with few of the DevOps setup for my client and got hands on to the Salesforce Developer Experience – the SFDX.

I’m not going into details of what is SFDX and its capabilities as those are covered by fellow bloggers. Instead, will focus on how you could authenticate SFDX with an org of any choice. And again, there are blogs on this as well. So what’s the next focus!?

Here on this blog, let’s forget about terms like scratch org, developer hub etc. Instead will make sure sfdx works for any “type” of org. I’m using my developer edition and the rules applies for a production or sandbox instance. Hmm… that’s a lot of prologue. Lets get started.


The below tools must be installed on your machine:

  • SFDX
  • OpenSSL

Flow in this tutorial


Setup SSL Certificate

This setup is required only for the purpose of this tutorial. As what we could generate is a self-signed certificate. A self-signed certificate is not recommended for use in a production instance. For a real project and application, you should go with a CA signed certificate. Don’t worry about the jargons, these are explained almost everywhere on internet. You could contact the ‘Digital Security’ team to procure a CA signed certificate. They would provide you with the required certificate and its key.

Install the openssl if you don’t have in your system using the below link and choose the version for your OS and don’t choose light version. After the installation, restart your machine and verify you have the openssl path variable set. This is the part I struggled a lot as getting an openssl binary was toughest part of this journey.

Create a folder ‘JWT’ in a directory of your choice, navigate to that directory on the command line and run the below commands one after the other.

openssl genrsa -passout pass:x -out server.pass.key 2048
openssl rsa -passin pass:password -in server.pass.key -out server.key
openssl req -new -key server.key -out server.csr

At this point, you need to enter few details which will be taken into consideration, while generating the certificate. After you complete entering the details, it will again prompt on the cli path. Enter the below command and hit enter.

openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

Now you can see four files in the folder of which two files are in need: server.key and server.crt. We will upload the server.crt file while we create a connected app and pass the server.key along when we make the connection – in this case through the sfdx command.


Setup Connected App

Time to login to salesforce. Login to your developer edition and create a connected app. Check the ‘Enable OAuth Settings’ & ‘Use Digital Signatures’. Your app should have details as below screenshots. Upload the server.crt file under the digital signature.


Run SFDX Commands

All set. Now its time to test the connection using the sfdx auth command. Run the below sfdx command. I’ve kept the server.key file in the location: C:\JWT\server.key

sfdx force:auth:jwt:grant -u <username> -f C:\JWT\server.key -i <cosumerkey> -r

As you see from the above image, the SFDX got authenticated using the JWT. The command used the key with which the certificate was generated and connected to sfdc using the consumer key app that uses that certificate. Be very careful with the key file as it holds the pass to your org.


Blog at

Up ↑