Skip to main content

Is there any way to write code to call an apex function from within skuid?

Ant, there are 4 main ways to call Apex functions from within Skuid: 1. Use the AJAX toolkit’s “sforce.apex.execute()” method to execute an Apex Web Service (requires you putting your Apex logic into a Web Service) 2. Use the Salesforce Apex REST technology to expose your methods as an Apex REST Service, and then callout to this using jQuery get() or similar calls. 3. Have your Apex logic initiated by Triggers — so that when you make data changes from within Skuid, such as changing the Status of a record, back-end Apex is kicked-off. 4. (probably what you want to do) Rather than initiating Skuid from Redirects, have your Visualforce Override pages actually include Skuid Pages through the


<skuid:page ipage=pageName] gactionType=actionType objectType=objectType]>

Visualforce Component. That way, you can have a custom Apex controller / controller extension for your Visualforce Page, which contains your Apex functions, BUT you can still have your Skuid Page. We recommend making your Apex logic into JavaScript Remoting methods, so that it’s easy to execute them from JavaScript. Using actionFunctions to kick off Apex logic may be problematic. Example Visualforce Page:


<apex:page docType="html-5.0" readOnly="true" standardController="Account" extensions="MyApexClass"> <skuid:page page="MySkuidPage"/> </apex:page> 

Example Apex Class:


public with sharing class MyApexClass { @RemoteAction public static Account createAccount(String accountName) { Account a = new Account(Name = accountName); return a; } } 

Example use from within Skuid JavaScript code (e.g. a Snippet):


var newAccount = MyApexClass.createAccount('Acme Generators'); alert('New Account Id: ' + newAccount.Id); 

I have written some code I need to run before I call the skuid page… it creates a running balance entry on a series of charges for an account. Can I use this last method in a way that makes sure the running balance code runs before the skuid page loads ?


Here is an example of how to do strategy 1: using the AJAX Toolkit to execute Apex code defined as a Web Service. 1. Ensure that you have your Apex code defined as a Web Service Here is a dummy Apex class that exposes two Web Service methods, “Prequalify” and “SubmitForProcessing”: 2. In your Skuid Page, add the Apex from AJAX toolkit as a new “External” JavaScript Resource: (a) Go to your page’s Resources tab (b) Click on “JavaScript”. Click the green plus icon that appears to the right to add a new JavaScript Resource. (c) Click on your newly-created JavaScript Resource. Change its type to “External”. (d) For Resource URL, put /soap/ajax/29.0/apex.js This is VERY important, and must be done on all Skuid Pages from which you wish to leverage the “Apex via AJAX Toolkit” approach. Skuid automatically always loads in the base AJAX Toolkit JavaScript (/soap/ajax/ilatest_version]/connection.js), so all you need to do is load in the Apex library. 3. In your Skuid Page, add a new JavaScript Resource of type “Inline (Snippet)” which will contain your button-calling logic: We are going to add a new Snippet called “Prequalify”, which will call our Prequalify web service in our OpportunityUtils class, passing in a parameter “opportunityId”, which will contain the Id of the Opportunity record we are interested in: 4. Add a new button to your Page Title, of type “Custom: Run Skuid Snippet”, which is set to call the “Prequalify” Snippet: Result: a button which runs your Apex web service on the selected Opportunity, and returns the result.


Zach,

I gave this a try but unfortunately, I’m getting an error message:

faultcode:‘soapenv:Client’, faultstring:‘No operation available for request {http://soap.sforce.com/schemas/package/MyClass}myMethod, please check the WSDL for the service.’ 
Any idea what might be going on?  I set it up exactly as you described.


According to this post: https://developer.salesforce.com/forums/ForumsMain?id=906F00000008wk5IAA you might have forgotten to use the “Webservice” keyword on your apex method.


Moshe, no I didn’t.

It actually turns out that the apex toolkit for whatever reason converts the case on the webservice method.  I changed the method name from myMethod to MyMethod and it work.  Weird


Bottom line… I’m glad it worked for you.


Could we access the webservice objects within javascript too? for example this:


global&nbsp;class&nbsp;TestInvocable<br />{<br />&nbsp;&nbsp;&nbsp;global&nbsp;class&nbsp;DispatchInfo&nbsp;<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;webservice&nbsp;Date&nbsp;dispatchDate;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;webservice&nbsp;String&nbsp;shippingCompany;<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;webservice&nbsp;static&nbsp;String&nbsp;testInvocableMethod(DispatchInfo&nbsp;dispatch)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System&#46;debug('Dispatch&nbsp;info');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System&#46;debug('date:&nbsp;'&nbsp;+&nbsp;dispatch&#46;dispatchDate);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System&#46;debug('shipping&nbsp;company:&nbsp;'&nbsp;+&nbsp;dispatch&#46;shippingCompany);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;'Ok';<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}

I need to access the ‘DispatchInfo’ object within my code snippet. I tried doing something like this:


var dipatchInfo = sforce&#46;Xml('DispatchInfo'); 


but this doesnt work as dipatchInfo was always undefined. Any help on this would be appreciated. Thanks.


I’m not sure, would have to research, but an easier way would be to make your Apex method take a String argument, which is actually JSON, and then serialize client-side to JSON and deserialize server-side into a DispatchInfo object, e.g.


global&nbsp;class&nbsp;TestInvocable

{<br>&nbsp;&nbsp;&nbsp;private&nbsp;class&nbsp;DispatchInfo&nbsp;<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;dispatchDate;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;shippingCompany;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;webservice&nbsp;static&nbsp;String&nbsp;testInvocableMethod(String&nbsp;dispatchJSON)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DispatchInfo dispatch = (DispatchInfo) JSON.deserialize(dispatchJSON,DispatchInfo.class);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.debug('date:&nbsp;'&nbsp;+&nbsp;dispatch.dispatchDate);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.debug('shipping&nbsp;company:&nbsp;'&nbsp;+&nbsp;dispatch.shippingCompany);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;'Ok';<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>} 

And then in JavaScript you could do this (if you’re using the AJAX Apex Toolkit):

var dispatch = {
    dispatchDate: new Date(),
    shippingCompany: “Acme”
};
var result = sforce.apex.execute(“TestInvocable”,“testInvocableMethod”,{ dispatchJSON: JSON.stringify(dispatch) });
console.log('the result was: ’ + result);



This is what I needed…thanks.


hii guys i tried to do that opportunity example i paste the code in snippet and in a button i select snippet name but its not working for me means that on click event nothing happens what wrong did i do can anyone tell me


Two questions: 

  1. Does the new action framework action “Run Custom Apex Action” change any of this?

  2. If we pursue option 2 and expose APEX methods as a REST service, can we then build a skuid REST API model against that service?


bump.


  1. If you expose your apex logic as Apex Invocable Methods, then you can call the logic through the “Run Custom Apex Action”. This approach is good if the Apex logic has a general purpose, such as “Send SMS via Twilio”, and thus should be available to call from any Skuid Page. You can lock down access to Invocable Apex Classes via Profile / Permission Sets, but not by execution context (e.g. VF Page), so If you need to lock down access to this Apex to be from a particular execution context, then the Remote Action approach would be better.
    2. REST Models are a great alternative, yes! The nice thing about this approach is that you can then use regular Skuid Model API methods to, in effect, influence Apex code. Highly recommended.


Hey Zach,
    I used the 4th option that you suggested. Embedded the Skuid Page in my visualforce page. I used the following script in my JavaScript Snippet
alert(‘hi’);
var newAccount = TestAccountEntrySkuid.createAccount();
alert('New Account Id: ’ + newAccount.Id);

When I click on the button for which I have configured the above Java Script Snippet, it only shows the first alert and post that nothing happens.
Am I missing anything here???
My Controller contains a blank constructor and a method to insert an account record. Method annotation is @RemoteAction .


Are there any errors in the JavaScript Console when you run this?


Hey Gautam,

I ran into same issue few days ago, on console you should have an error, saying that remoting error for VF remoting - missing parameters or something similar.

Try to use the function call like below and see. (it always expects callback function, so i modified like below and works for me)


TestAccountEntrySkuid.createAccount(function(result){

alert('New Account Id: ’ + result.Id);
});



Hello Zach, 
       Uncaught ReferenceError: TestAccountEntrySkuid is not defined . This is the exception that I encounter in the console. Is there anything that I need to do specifically? The method is static, so I assumed that ‘TestAccountEntrySkuid.createAccount();’ should take care of calling the method directly.

Regards,
Gautam.


Hey Kvin, 
   Following is the error in the console that I am getting:-
 Uncaught ReferenceError: TestAccountEntrySkuid is not defined ,


Hey Gautam,


I believe you are trying to preview the Skuid page alone and trying to use your class to work as extension.


Did you add this class as an extension to your VF page as Zach explained in above initial posts ?


<apex:page docType=“html-5.0” readOnly=“true” standardController=“Account” extensions=“TestAccountEntrySkuid”>


<skuid:page page=“MySkuidPage”/>


</apex:page>

Try to preview this VF page once created, that should resolve the issue.


Are there any tutorials for building a REST model to access a webservice in apex?


We have been successfully using option 1 mentioned by Zach at the top of this post i.e the AJAX toolkit’s sforce.apex.execute method. But we are receiving errors when we try to expose the same skuid page in the salesforce community. I see an error in the console that indicates it may be an error related to the External resource /soap/ajax/29.0/apex.js that is added to the skuid page. Here is the console error:

apex.js:48 Uncaught TypeError: Cannot read property ‘push’ of undefined

at sforce.Apex.execute (https://stagefull-afl.cs52.force.com/soap/ajax/37.0/apex.js:48:61)

at https://stagefull-afl.cs52.force.com/Customer/resource/1504866722000/AFLInquiryOrderResourceWorkflow…

at Object.callback (eval at (https://stagefull-afl.cs52.force.com/Customer/resource/1495240238000/skuid__JQueryJS:2:13735), :150:64)

at Object.K.aa.when.all.then.c (https://stagefull-afl.cs52.force.com/Customer/resource/1496757765000/skuid__SkuidJS:8:17252)

at Object. (https://stagefull-afl.cs52.force.com/Customer/resource/1495240238000/skuid__JQueryJS:3:7502)

at j (https://stagefull-afl.cs52.force.com/Customer/resource/1495240238000/skuid__JQueryJS:3:6134)

at Object.fireWith ias resolveWith] (https://stagefull-afl.cs52.force.com/Customer/resource/1495240238000/skuid__JQueryJS:3:6946)

at Object.e.(anonymous function) nas resolve] (https://stagefull-afl.cs52.force.com/Customer/resource/1495240238000/skuid__JQueryJS:3:7926)

at Object. (https://stagefull-afl.cs52.force.com/Customer/resource/1496757765000/skuid__SkuidJS:2:6047)

at Object. (https://stagefull-afl.cs52.force.com/Customer/resource/1495240238000/skuid__JQueryJS:3:7502)

sforce.Apex.execute @ apex.js:48


Any ideas?


Just to let everyone know calling apex from skuid in a salesforce community using sforce.apex.execute is not an issue. The above issue was caused by an undefined variable being passed to the apex class. The error message returned was very ambiguous. Hopefully this will save somebody a lot of frustration.


Is there documentation on using classes exposed with REST with Skuid? I must not be setting authorization correctly.


still haven’t been able to get REST to work