4

We have JavaScript buttons that follow this pattern:

{!REQUIRESCRIPT('/soap/ajax/39.0/connection.js')}
{!REQUIRESCRIPT('/soap/ajax/39.0/apex.js')}

var ok = confirm('Create the Interest Adjustment?');
if (ok) {
    var result = sforce.apex.execute(
            'InterestRulesActions',
            'addInterestToPayment',
            {paymentId: '{!Payment__c.Id}'}
            );
    if ('success' == result) {
        // See the changes
        window.location.reload();
    } else {
        // See the error message
        alert(result);
    }
}

calling server methods of this nature:

global class InterestRulesActions {

    webservice static String addInterestToPayment(Id paymentId) {
        ...
    }
}

Such buttons are no longer rendered in Lightning Experience and so require rework if "Lightning Ready" status is to be maintained.

A Lightning Action that invokes a Lightning Component appears to be the way to go. Is the best (and maybe the only) way to directly re-use the server-side code to add @AuraEnabled to each method so it can be easily called from the Lightning Component:

global class InterestRulesActions {

    @AuraEnabled
    webservice static String addInterestToPayment(Id paymentId) {
        ...
    }
}

This compiles; does it work?

6
  • Have you tried it? It seems like it should work.
    – sfdcfox
    Commented Jun 27, 2018 at 12:49
  • Is this a detail page button? It looks very straight forward. Commented Jun 27, 2018 at 12:53
  • @sfdcfox Was wondering if there is any way to directly call the webservice method. Though I'm now thinking of having a single generic component that dispatches to the the relevant piece of existing code so that is now a moot point.
    – Keith C
    Commented Jun 27, 2018 at 14:14
  • @RajeshVarmaMudunuri Yes it is a detail page button.
    – Keith C
    Commented Jun 27, 2018 at 14:14
  • Are you asking if you can call the web service without have to go to server like a client side callout? Because you already have the information you need you just have to call the apex method from your quick action component which has the logic you have on the existing java script button. Can you make it little clear for me on what your'e looking for? Commented Jun 27, 2018 at 14:30

3 Answers 3

4

Components can only have one controller, so assuming this is a generic utility called all over the place, odds are, no, you won't be able to do this directly. If you look at force:recordData, you'll see that having a "generic" utility component that can interact with a particular service can be a viable design. You'd hook everything up with aura:method, and then you can call your service:

component.find("InterestRulesAction").addInterest(recordId, result => ...);

There's several ways you can design your API, but since you do need a call to the server, you'll need to specify a callback method so you can get the results later.


Since Lightning Session IDs don't have full API access, it shouldn't be possible to call the webservice method without @AuraEnabled. You will definitely need to call an @AuraEnabled method to (eventually) reach this method if choose to call it indirectly.

4

Thanks to Rajesh and Brian for their insight that I've taken on board. My answer here outlines what I plan to do, which is substantially also driven by the large number (around 50) of these buttons that I need to replace.

At the server-side a single entry point that dispatches to the existing webservice methods seems a simple way to go:

public with sharing class QuickActionController {
    @AuraEnabled
    public static void execute(String operation, String argumentsJson) {
        if (operation == 'InterestActions.addToPayment') {
            Id paymentId = ...;
            String success = InterestActions.addToPayment(paymentId);
            if (success != 'success') throw new AuraHandledException(success);
            }
        } else if (...) {
            ...
        }
        ...
    }
}

Then for the main component:

<aura:component controller="QuickActionController">
    <aura:attribute name="confirmation" type="String" required="true"/>
    <aura:attribute name="operation" type="String" required="true"/>
    <!-- UI -->
</aura:component>

but it looks like there is no way to inject values from the action definition so a separate component will be needed for all 50 that sets the parts that vary. This could be by composition:

<aura:component>
    <c:quickAction
            confirmation="Create the Interest Adjustment?"
            operation="InterestActions.addToPayment"
            />
</aura:component>

but inheritance might offer more flexibility.

7
  • I like this approach, most of the time i find it useful to have a wrapper component on top of quick action to have more control and flexibility over it! Commented Jun 27, 2018 at 15:19
  • @RajeshVarmaMudunuri Good to know. Don't want to set off creating 50 components that aren't needed...
    – Keith C
    Commented Jun 27, 2018 at 15:20
  • You don't need 50 components, What type of values are you trying to inject for each of these? Commented Jun 27, 2018 at 15:23
  • @RajeshVarmaMudunuri I'd be delighted if not... The values are a confirmation message and the server-side value to switch on - see my last aura:component example.
    – Keith C
    Commented Jun 27, 2018 at 15:25
  • 1
    Let us continue this discussion in chat. Commented Jun 27, 2018 at 15:50
3

You won't be able to re-use your existing web service methods directly without having to annotate them with auraEnabled.

In this case i only see two options.

  1. Use auraEnabled annotation
  2. Do a client side call out without even touching apex code.(Which i wouldn't recommend)

So i believe you are stuck with option number 1.

If you choose option 2. Below are things to keep in mind.

By default, you can’t make calls to third-party APIs from client-side code. Add a remote site as a CSP Trusted Site to allow client-side component code to load assets from and make API requests to that site’s domain.

The Lightning Component framework uses Content Security Policy (CSP), which is a W3C standard, to control the source of content that can be loaded on a page. Lightning apps are served from a different domain than Salesforce APIs, and the default CSP policy doesn’t allow API calls from JavaScript code. You change the policy, and the content of the CSP header, by adding CSP Trusted Sites.

Sometimes, you have to make API calls from server-side controllers rather than client-side code. In particular, you can’t make calls to Salesforce APIs from client-side Lightning component code.

Making API Calls from Components

you need to leverage the Xml http request object Making API calls to third party API from Lightning component in client-side

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .