Salesforce JavaScript Remoting: Using Apex and JavaScript objects to pass data from client- to server-side and vice versa

I’ve spoken about how to do this at a high level during Cloudstock London and there are hints at how it can be done but no formal documentation that I’ve found, so here we are 🙂

Quite simply JavaScript Remoting will transform Apex objects and classes (or collections of these types) into JavaScript objects for you. The opposite is true too but there are some rules you need to observe.

Apex Types to JavaScript Equivalents

This is the easier of type conversions in that you don’t have to really do anything to make it happen. The code below uses a custom class that I’ve defined but you can do the same with any sObject too. Let’s have a look at the code.

The Controller

public with sharing class RemotingObjectsController {
 
    /* The remoting method simply instantiates a two custom types, puts
       them into a list and then returns them. */
    @RemoteAction
    public static List<CustomClass> getClassInstances(){
        List<CustomClass> classes = new List<CustomClass>();
 
        CustomClass me = new CustomClass('Wes');
        CustomClass you = new CustomClass('Champ');
 
        classes.add(me);
        classes.add(you);
 
        return classes;
    }
 
    /* My custom type */
    public class CustomClass{
        public String firstName{get;set;}
 
        CustomClass(String firstName){
            this.firstName = firstName;
        }
    }
}

The Visualforce

<apex:page controller="RemotingObjectsController">
  <script>
      // Will hold our converted Apex data structures
      var classInstances;
 
      Visualforce.remoting.Manager.invokeAction(
        '{!$RemoteAction.RemotingObjectsController.getClassInstances}',
        function(result, event) {
          // Put the results into a var for pedantries sake
          classInstances = result;
 
          console.log(classInstances);
 
          // Assign the first element of the array to a local var
          var me = classInstances[0];
 
          // And now we can use the var in the "normal" JS way
          var myName = me.firstName;
          console.log(myName);
        });
  </script>
</apex:page>

The Output

Console output from the JS code.

JavaScript Types to Apex Equivalents

This is a little tricker, especially when it comes to sObjects. Note that the approach below works for classes and sObjects too.

The Visualforce Page

<apex:page controller="RemotingObjectsController">
  <script>
      /* Define a JavaScript Object that looks like an Account */
      /* If you were using custom objects the name must include the "__c" */
      function Account(){
          /* Note the field names are case-sensitive! */
          this.Id = null; /* set a value here if you need to update or delete */
          this.Name = null;
          this.Active__c = null; /* the field names must match the API names */
      }
 
      var acc1 = new Account();
      acc1.Name = 'Tquila';
      acc1.Active__c = 'Yes';
 
      var acc2 = new Account();
      acc2.Name = 'Apple';
      acc2.Active__c = 'Yes';
 
      var accounts = new Array(acc1, acc2);
 
      Visualforce.remoting.Manager.invokeAction(
        '{!$RemoteAction.RemotingObjectsController.insertAccounts}',
        accounts,
        function(result, event) {
          console.log(result);
        });
  </script>
</apex:page>

The Controller

There is not much to the controller in this case.

public with sharing class RemotingObjectsController {
 
    @RemoteAction
    public static void insertAccounts(List<Account> accounts){
        insert accounts;
    }
 
}

Why is this cool?

Good question. If the Force.com Platform didn’t do this for you then we – the developer – would need to convert ours types explicitly on both the server-side and the client-side, and man-oh-man is that boring, error-prone work. Yet again the guys at salesforce.com have built in a convenience that saves us time and let’s us get on with the work of building cool apps.

14 thoughts on “Salesforce JavaScript Remoting: Using Apex and JavaScript objects to pass data from client- to server-side and vice versa”

  1. Hi nice post,
    I have a question –

    You talked about the object which are already defined in salesforce. I want to send a map to the remote method. Is there any trick. I am also trying with jquery serialize array to send the json data to the remote method but dont know its not working.

    This will help you to understand what I want

    https://sites.secure.force.com/success/servlet/rtaImage?eid=a1X30000000dkOn&feoid=00N30000006WEw0&refid=0EM300000016hdr

    Thanks in advance.

    Reply
  2. I understand this is probably basic knowledge for most devs but I fought with this example for hours after realizing you forgot to add a comma in the most important part of the jQuery code.
    Visualforce.remoting.Manager.invokeAction(
    ‘{!$RemoteAction.RemotingObjectsController.insertAccounts}’,
    accounts, <———————-missing comma
    function(result, event) {
    console.log(result);
    });

    I definitely was able to use this to my benefit though so no worries 🙂

    Just please add the comma

    Reply
  3. Hi!
    There is a far more readable notation for this call:

    RemotingObjectsController.insertAccounts(accounts,function(result, event) {
    console.log(result);
    });

    Cheers,
    Detlef

    Reply
  4. The platform does a great job of converting data to the Javascript equivalent in most cases… I’ve found that Date objects are a tricky exception. If you have a remoted method with SObjects as a parameter (or contained in a parameter, such as List), field values of type “date” are serialized as the integer milliseconds-since-epoch UTC value for midnight on that date, and appear to you as strings. Constructing a local Date from this naively can result in dates that are one day off. The following is my fix, interposed wherever in your (Javascript) code it makes sense:

    var datefield = new Date(parseInt(datefield_from_server)); // string returned in remoted method response
    datefield = new Date(datefield.getUTCFullYear(), datefield.getUTCMonth(), datefield.getUTCDate());

    Javascript experts probably have a better way, but it works for me…

    Reply
  5. I’m still having a hard time seeing the advantage of remoting over the AJAX toolkit. Have you tried both or can you offer some input?

    Reply
    • Sure. The AJAX toolkit is a wrapper on the webservices API and is based on the partner WSDL. Remoting let’s you call (specially annotated) Apex Controller methods from JavaScript in your Visualforce.

      Reply
      • Thanks for the explanation. I guess what I’m getting at is in the example provided you’re just doing a DML operation which you could do just as easily with the AJAX toolkit without a controller action. Maybe I just need to dig up a more complex example to see the additional benefits.

        Reply
  6. Hi Wes,
    I was wondering if you had ever seen this error before: Uncaught TypeError: Cannot read property ‘CLASS_NAME’ of undefined, VFRemote.js line 122. My javascript remoting is throwing this error.

    Here’s what I’m confused about. This code works:
    RemoteClassController.remoteMethod(param1,param2,param3,handleUpdatesCheck);
    but this code doesn’t:
    Visualforce.remoting.Manager.invokeAction(‘{!$RemoteAction.RemoteClassController.remoteMethod}’,param1,param2,param3,handleUpdatesCheck);

    where handleUpdatesCheck is another function that handles the results. Do you have any idea why the first option works but the second doesn’t? I’d like your input because we’re using a managed package and I’d really like to avoid having to hack together a solution for managed/unmanaged if possible and I know the second option works both inside and outside of the package. Until then, I will use your workaround here: http://th3silverlining.com/2012/02/26/salesforce-javascript-remoting-and-managed-packages/

    Thanks again!
    –Liz

    Reply

Leave a Comment