Today I want to go through some of the options we have for calling Apex from Javascript inside a Visualforce page, ActionFuntion and Javascript Remoting.
First of all, I would like to explain how ActionFunction works. With actionFunction, what we achieve is to have a javascript function which is mapped to the controller method that you want to call.
For example, I want to load an account in my controller instance and then show its name, all from javascript, I could create the next controller and visualforce page:
public with sharing class MyController { public Account MyAccount {get; set;} public PageReference getAccount() { String accountName = Apexpages.currentPage().getParameters().get('accountName'); MyAccount = [SELECT Name FROM Account WHERE Name = :accountName]; return null; } }
<apex:page controller="MyController"> <apex:form > <apex:actionFunction name="getAccountMappedFunction" action="{!getAccount}" oncomplete="doOnComplete('{!MyAccount.Name}');"> <apex:param name="accountName" value="GenePoint"/> </apex:actionFunction> </apex:form> <script > getAccountMappedFunction(); function doOnComplete(name) { alert(name); } </script > </apex:page>
What we are doing here is defining a javascript function (getAccountMappedFunction) mapped to my controller method (getAccount), and calling it from javascript. When calling the actionFunction, the form in which it is enclosed will be posted.
What this does behind the scenes is no more than an Ajax request. This means that the page is not going to be frozen waiting for the server code to execute, and users will continue being able to interact with the page. However, you can define some logic to be executed once the server logic has finished, with the oncomplete attribute, or you can render again some areas of the page with the rerender one.
Using an actionFunction:
- You can use a rerender attribute, to render an area of the page once the request has finished.
- You don’t have to write any javascript, except the call to the function when you need it.
- The form in which the actionFunction is enclosed will be posted and the viewstate will be transferred to the server.
- You can pass parameters in using apex:param.
- You cannot directly use a type returned by the server method.
What about using Javascript Remoting? Let’s try to do the same:
public with sharing class MyController { @RemoteAction public static Account getAccountRemote(String accountName) { return [SELECT Name FROM Account WHERE Name = :accountName]; } }
<apex:page controller="MyController"> <script > function getRemoteAccount() { var accountName = 'GenePoint'; Visualforce.remoting.Manager.invokeAction( '{!$RemoteAction.MyController.getAccountRemote}', accountName, function(result, event){ alert(result.Name); } ); } getRemoteAccount(); </script > </apex:page>
Here what we are doing is exactly the same as before, an Ajax call to the static method that we have defined as remote in our controller (getAccountRemote), which has to be static compulsorily. As with actionFunction, the Javascript call won’t block the user interaction. Also we can write a callback function that will be executed once the server has finished the processing.
Using Javascript Remoting:
- We have passed in a parameter in directly with Javascript.
- We have been able to define a callback, that takes the account returned from the method.
- If we would like, we could have controlled certain parameters of the request, as the timeout, or the grouping of requests.
- As no form has been posted, no viewstate has been sent to the server, which means it has been a more efficient call than the actionFunction.
- We haven’t been able to render an area of the page simply using a rerender tag, as we could do with actionFunction. If we would like to modify the DOM, we would need to do some additional processing.
Then, when to use what? Well, if your request needs to update an area of the DOM, I’d use actionFunction as it has built-in support for it. However, if you need to get some data in a light and fast way (typically an auto-complete feature), or simply do an action without refreshing the page, Javascript Remoting can be the option for you.
Leave a Reply