Grails asynchronous view loading with remoteFunction

This is in no way anything new, i just wanted to share an example of a really nice approach (imo) on how you can load some operation heavy rendering asynchronously using the grails remoteFunction. Assuiming that you have a database with a large dataset that you want to aggregate and render in some fashion on a gsp page , but you do not want to stall the pageload opon navigation.

In our gsp we could add something similiar to this..

<div>
  <span class="data-loading-spinner"><r:img uri="/images/spinner.gif"/></span>
  <div id="table_data"></div>
</div>

Opon pageload we will se a loading spinner waiting to be replaced with the actuall data… Since we want to load the table data when the page has fully loaded, we do this by issuing a remote call opon document.ready

<r:script>
$(document).ready(function() {
    ${remoteFunction(
        controller:'home',
        action:'render_table_data',
	update:'table_data',
	onLoading:'$(".data-loading-spinner").removeClass("hidden");',
	onComplete:'$(".data-loading-spinner").addClass("hidden");'
    )};
});
</r:script>

The remoteFunction will show the data-loading-spinner during the issuing call, and add hidden to it as soon as it returns onComplete.

So what happens in the controller?

def render_table_data() {
  //here we do whatever to gather our data.. whether it is calling a service doing some queries to the database...
  //when finished, create a model object and render it using a separate template.
  def model = [table_data:table_data]
  render template:"table_data_template", model:model
}

table_data_template here is a separate gsp file that is in the same context as our home view.

<table>
  <thead>
    <tr>
      <th>Name</th>
        <th>Data</th>
    </tr>
  </thead>
  <tbody>
    <g:each in="${table_data}">
      <tr>
        <td>${it.name}</td>
        <td>${it.calculatedData}</td>
      </tr>
    </g:each>
  </tbody>
</table>
Written on February 23, 2014