Javascript Remoting & jQuery Templates: An Easy Way to Rich and High-Performance Interfaces!

Javascript Remoting & jQuery Templates Banner Image

Since the release of the Javascript remoting feature in the Spring’11 release, I was super excited about it and was looking for spare time to play with it.
A few days back I read about jQuery templates; that’s an awesome jQuery plugin (soon going to be part of jQuery Min).

jQuery templates contain markup with binding expressions (‘Template tags’). Templates are applied to data objects or arrays and rendered into the HTML DOM.

This templating engine supports powerful tag libraries inbuilt that support conditions and iterations. For more details, check this post. If you are coming from a J2EE background, you can treat this jQuery template feature very similar to Apache Velocity and free marker templates.

Using jQuery templates & Javascript Remoting together!

This mashup is important from a force.com development point of view because:

  • Remoting allows you to perform almost any apex logic via Javascript.

  • Using remoting, one can bypass all the hassle of viewing state and performance issues because of that on complex Visualforce screens.

  • Mashing up these two can result in very lightweight, super fast, and complex visual force screens with more human-readable code.

We will see a simple example below, where:

  • We search for accounts for a user-inputted account name using Remoting.

  • Display the search results in the Salesforce pageBlockStyle table without re-rendering and form submission. All using jQuery templates, the lines of code required to do so are trivial, and the markup is very straightforward to understand.

Code Snippet

This code snippet is pretty similar to what you must have already seen in Visualforce remoting docs. I only enhanced it for jQueryTemplate support to render a table easily. I am assuming you are already comfortable with basic Apex, HTML, jQuery, and Visualforce. The only suggested reading is jQueryTemplates; please have a quick look at this page before diving into the code below, for easy understanding.

Apex Controller – testremotingcontroller.cls

public with sharing class  testremotingcontroller {
    @RemoteAction
    public static Account[] searchAccounts(String accountName) {
        // support * search like salesforce lookups
        accountName = accountName.replaceAll('[*]', '%');
        return [select id, name, phone, type, numberofemployees from 
             Account where name like :accountName ];
        
    }   
}

Visualforce Page – testremoting.page

 
<apex:page controller="testremotingcontroller"> 
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"/>
<apex:includeScript value="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"/>
<apex:sectionHeader title="Javascript Remoting & jQuery Templates !"/>
<apex:pageBlock title="Accounts">
 <!-- Section to draw search field for account -->
    <apex:pageBlockSection title="Search Accounts" columns="2">
        <apex:pageBlockSectionItem >
            Account Name :
            <input type = "text" id = "accountNameToSearch" />
            <button onclick="searchAccounts()">Get Account</button>
        </apex:pageBlockSectionItem>
    </apex:pageBlockSection>
 <!-- result section for showing matching accounts -->
    <apex:pageBlockSection title="Matching Accounts !" columns="1">
    <!--
    Created Empty table using the CSS styles of visualforce pageBlockTable
    This gives same look and feel
    -->
    <table cellspacing="0" cellpadding="0" border="0" id="searchResults" class="list ">
        <colgroup span="2"></colgroup>
        <thead class="rich-table-thead">
            <tr class="headerRow ">
                <th colspan="1" scope="col" class="headerRow">Id</th>
                <th colspan="1" scope="col" class="headerRow"> Name</th>
                <th colspan="1" scope="col" class="headerRow"> Phone</th>
                <th colspan="1" scope="col" class="headerRow">Type</th>
                <th colspan="1" scope="col" class="headerRow"> Number of Employees</th>
            </tr>
        </thead>
    <!-- table body left empty for populating via row template using jquery -->
        <tbody />
    </table>
    </apex:pageBlockSection>
</apex:pageBlock>
<!--
Create a named jquery template
This template represents just a result row, with binding variables for each queried field from account.
-->
<script id="resultTableRowTemplate" type="text/x-jquery-tmpl">
<tr onfocus="if (window.hiOn){hiOn(this);}" onblur="if (window.hiOff){hiOff(this);}" onmouseout="if (window.hiOff){hiOff(this);} " onmouseover="if (window.hiOn){hiOn(this);} " class="dataRow even first">
    <td class="dataCell">${Id}</td>
    <td class="dataCell">${Name}</td>
    <td class="dataCell">${Phone}</td>
    <td class="dataCell">${Type}</td>
    <td class="dataCell">${NumberOfEmployees}</td>
</tr>
</script>
<script type="text/javascript">
// if you are inside some component
// use jquery nonConflict
// var t$ = jQuery.noConflict();
function searchAccounts() {
    var accountName = $('#accountNameToSearch').val();
    // clear previous results, if any
    $("#searchResults tbody").html('');
    // The Spring-11 gift from force.com. Javascript remoting fires here
    // Please note "abhinav" if my org wide namespace prefix
    // testremotingcontroller is the Apex controller
    // searchAccounts is Apex Controller method demarcated with @RemoteAction annotation.
    // DEPRECATED - abhinav.testremotingcontroller.searchAccounts( accountName, ...)
    // NEW - summer'12 approach for calling
    Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.testremotingcontroller.searchAccounts}',
                   accountName, function(result, event){
        if (event.status && event.result) {
          $.each(event.result, function () {
             // for each result, apply it to template and append generated markup
             // to the results table body.
             $("#resultTableRowTemplate" ).tmpl(this).appendTo( "#searchResults tbody" );
          }
         );
        } else {
           alert(event.message);
        }
    }, {escape:true});
}
</script>
</apex:page>
 

Where I got stuck with JavaScript Remoting?

I was planning to present a richer demo with the ability to inline edit the Account’s phone on blur, i.e., you change any “Phone” displayed on the grid, and on leaving the cell it will update the account via Remoting. But somehow Javascript seems to roll back the Account updates silently.

I posted that as a question on the discussion board. Almost the same code as above is in this discussion board question; if any of you have any clue, please share it with the rest of us!

References

Related Reading

Visualforce Salesforce jQuery Ajax, how to?

Let’s Talk

CTA Banner

Drop a note below to move forward with the conversation 👇🏻

Abhinav Gupta

First Indian Salesforce MVP, rewarded Eight times in a row, has been blogging about Salesforce, Cloud, AI, & Web3 since 2011. Founded 1st Salesforce Dreamin event in India, called “Jaipur Dev Fest”. A seasoned speaker at Dreamforce, Dreamin events, & local meets. Author of many popular GitHub repos featured in official Salesforce blogs, newsletters, and books.

https://abhinav.fyi
Previous
Previous

Is Javascript Remoting == ViewStateLess Visualforce ?

Next
Next

Apex API String.format(); Exploring Good & Bad Parts!