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 .