[SalesForce] How to get a spinner on Quick Action LWC

With Summer '21, we have the ability to create a Quick Action from a LWC.

The Quick Action doesn't use any of the HTML I can write in this component :

This may sound familiar if you recall writing JavaScript buttons in the past. One of the key differences between a screen action and a headless action is that you don’t need the HTML file in your LWC.

But I want to include a Spinner.
I search for many ideas, creating another component which include just a spinner, but it seems really hard to open and close this component from the first one.
I also didn't find any way to call a spinner by the JS without the HTML

There is my code :

getAccountReport.js

import { LightningElement, api, track } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import getAccountReport from '@salesforce/apex/WS_Account_Report.getAccountReport';


export default class GetAccountInfosQALWC extends LightningElement 
{
    @api recordId;
    @api invoke() {
        //Here i'm sending a Toast message as a workaround
        //But I want the spinner starting here
        this.showToastMessage(1,'We are getting your report in few seconds...');
        getAccountReport({accId : this.recordId })
            .then((result) => {
                //I want the spinner to stop here
                if(result != true && result != 'true'){
                    this.showToastMessage(1,result);
                }
                else{
                    this.showToastMessage(2,'The report was successfully downloaded');
                    eval("$A.get('e.force:refreshView').fire();");
                }
            })
            .catch((error) => {
                console.log(error);
            });
        
    }

    showToastMessage(fromWho, mess, urlToast) {
        var variantToast;
        var titleToast;
        if(fromWho == 1){
            variantToast = 'info';
        }
        else if(fromWho == 2){
            variantToast = 'success';
            titleToast = 'Success'
        }
        const toastMessage = new ShowToastEvent({
            title: titleToast,
            message: mess,
            variant: variantToast,
            messageData: [
                {
                    url: urlToast,
                    label: 'here'
                }
            ]
        });
        this.dispatchEvent(toastMessage);
    }
}

getAccountReport.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordAction</target>
    </targets>
     <targetConfigs>
    <targetConfig targets="lightning__RecordAction">
      <actionType>Action</actionType>
    </targetConfig>
  </targetConfigs>
</LightningComponentBundle>

I already tested to put the spinner in the HTML, that's not working.

Best Answer

As you want to display a spinner, you will need to use the screen action instead of the headless action. Call the apex method(getAccountReport) as soon as the record id is passed down to the component. I don't know why the record id is not present in connectedCallack, so thought of an alternative way to call this from the setter method of the recordId.

Here is the code I tried.

// add your imports here.
export default class GetAccountInfosQALWC extends LightningElement {
    @api
    get recordId() {
        return this._recordId;
    }
    set recordId(value) {
        this._recordId = value;

        if (this._recordId) {
            this.callApex();
        }
    }

    _recordId;
    isLoading = true;

    callApex() {
        getAccountReport({ accId: this.recordId })
            .then((result) => {
                if (result != true && result != "true") {
                    this.showToastMessage(1, result);
                } else {
                    this.showToastMessage(
                        2,
                        "The report was successfully downloaded"
                    );
                    eval("$A.get('e.force:refreshView').fire();");
                }
                // call close quickAction
                this.closeAction();
            })
            .catch((error) => {
                console.log(error);
            })
            .finally(() => {
                this.isLoading = false;
            });
    }

    closeAction() {
        this.dispatchEvent(new CloseActionScreenEvent());
    }
}

Refer to this post: how to close quick action programmatically.

Note: Please note that you will need to remove the action from the page layout in order to change the type of action.

Related Topic