{page.title}

Grails Ajax List with Paging and Sorting

You can easily add ajax to your grails application using standard g tags, but making a list (table) that supports ajax-enabled sorting and paging is a bit different. Here are the steps I took to make this happen.

First I started with my controller action. I’m using single action for the list page as well as the ajax request to update the table data. It’ll look something like this:

def list = {
      params.max = Math.min(params.max ? params.int('max') : 20, 100)
      def model = [userInstanceList: User.list(params), userInstanceTotal: User.count()]

      if (request.xhr) {
          // ajax request
          render(template: "grid", model: model)
      }
      else {
           model
      }
}

A regular request uses the standard list view, but an ajax request is going to use a view template that contains just the HTML for our table along with its pagination links. Here’s an example of what these views might look like:

list.gsp

<html>
    <head>
        <meta name="layout" content="main" />
        <g:set var="entityName" value="${message(code: 'user.label', default: 'User')}" />
        <title><g:message code="default.list.label" args="[entityName]" /></title>
    </head>
    <body>

        <h2><g:message code="default.list.label" args="[entityName]" /></h2>

        <g:if test="${flash.message}">
          <div class="message">${flash.message}</div>
        </g:if>

           <p>
          <g:link class="button create" action="create"><g:message code="default.new.label" args="[entityName]" />
          </g:link>
          </p>

        <div id="grid">
           <g:render template="grid" model="model" />
        </div>

    </body>
</html>

_grid.gsp

<table class="ajax">
    <thead>
        <tr>
            <g:sortableColumn property="id" title="${message(code: 'user.id.label', default: 'Id')}" />
            <g:sortableColumn property="isActive" title="${message(code: 'user.isActive.label', default: 'Is Active')}" />
            <g:sortableColumn property="name" title="${message(code: 'user.name.label', default: 'Name')}" />
       </tr>
    </thead>
    <tbody>
    <g:each in="${userInstanceList}" status="i" var="userInstance">
        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
            <td><g:link action="show" id="${userInstance.id}">${fieldValue(bean: userInstance, field: "id")}</g:link></td>
            <td><g:formatBoolean boolean="${userInstance.isActive}" ></td>
            <td>${fieldValue(bean: userInstance, field: "name")}</td>
         </tr>
    </g:each>
    </tbody>
</table>

<div class="pagination">
	<g:paginate total="${userInstanceTotal}" />
</div>

Finally we’ll just need to add a little jQuery to turn these sorting and paging links into ajax requests.

$(document).ready(function() {
    setupGridAjax();
});

// Turn all sorting and paging links into ajax requests for the grid
function setupGridAjax() {
    $("#grid").find(".paginateButtons a, th.sortable a").live('click', function(event) {
        event.preventDefault();
        var url = $(this).attr('href');

        var grid = $(this).parents("table.ajax");
        $(grid).html($("#spinner").html());

        $.ajax({
            type: 'GET',
            url: url,
            success: function(data) {
                $(grid).fadeOut('fast', function() {$(this).html(data).fadeIn('slow');});
            }
        });
    });
}

Overall a pretty simple and elegant solution. If you’re interested in taking this example a bit further with the addition of filtering, see my post Grails Ajax List with Paging, Sorting and Filtering.