How to invoke Apex from Lightning page layout without modal

In some cases, you need to place a button to Standard Salesforce Layout to invoke the Apex method without any confirmation or close buttons. If you work in Visualforce OnClick JavaScript is the best solution.

But JavaScript custom buttons may reduce application security and block compatibility with Lightning Experience. Salesforce advises against using these buttons.

Salesforce offers to use Actions in Lightning Experience. To use it you need to create custom Aura Component and it will be shown in the modal.

In most cases, we don’t need a modal to invoke a simple Apex method. Next, you will find some hacks to hide the modal.

First of all, you need to implement a simple Aura Component that implements the interface.  It allows you to hide the standard header and close and save button. Then you need to add lightning:spinner, lightning:notificationsLibrary components and some CSS through aura:html.


    <aura:html tag="style">
        .cuf-content {
            padding: 0 0rem !important;
        .slds-p-around--medium {
            padding: 0rem !important;
            overflow-y:hidden !important;
            height:unset !important;
            max-height:unset !important;
        .slds-fade-in-open {
            visibility: hidden !important;
        .slds-spinner_container {
            background-color: transparent !important;
        .closeIcon {
            display:none !important;

    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <aura:attribute name="recordId" type="String" />

    <lightning:notificationsLibrary aura:id="notify"/>

    <lightning:spinner variant="inverse" size="medium" />


When you will press to a button you will see just a spinner without any modal window.

Another important part is to add $A.get("e.force:closeQuickAction").fire(); to the controller. This event will close Quick Action automatically. In the controller, you can also invoke the Apex method and show Toast with any results.

    doInit : function(component, helper) {
        let recordId = component.get('v.recordId');
        var action = component.get("c.runSync");
        action.setParams({ 'recordId' : recordId });
        action.setCallback(this, function(response) {
                "variant": "success",
                "title": "Success",
                "message": "Sync has started"

In this case we just call Apex method and show a notification.

That all! Follow our LinkedIn page for tracking new worthwhile articles. Write to us, if you have any questions.