7.7.5 Ajax on the Server - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 2.3.8
7.7.5 Ajax on the Server
There are a number of different ways to implement Ajax which are typically broken down into:- Content Centric Ajax - Where you just use the HTML result of a remote call to update the page
- Data Centric Ajax - Where you actually send an XML or JSON response from the server and programmatically update the page
- Script Centric Ajax - Where the server sends down a stream of JavaScript to be evaluated on the fly
Content Centric Ajax
Just to re-cap, content centric Ajax involves sending some HTML back from the server and is typically done by rendering a template with the render method:def showBook() {
def b = Book.get(params.id) render(template: "bookTemplate", model: [book: b])
}
<g:remoteLink action="showBook" id="${book.id}" update="book${book.id}">Update Book</g:remoteLink><div id="book${book.id}"> <!--existing book mark-up --> </div>
Data Centric Ajax with JSON
Data Centric Ajax typically involves evaluating the response on the client and updating programmatically. For a JSON response with Grails you would typically use Grails' JSON marshalling capability:import grails.converters.JSONdef showBook() {
def b = Book.get(params.id) render b as JSON
}
<g:javascript> function updateBook(data) { $("#book" + data.id + "_title").html( data.title ); } </g:javascript> <g:remoteLink action="showBook" id="${book.id}" onSuccess="updateBook(data)"> Update Book </g:remoteLink> <g:set var="bookId">book${book.id}</g:set> <div id="${bookId}"> <div id="${bookId}_title">The Stand</div> </div>
Data Centric Ajax with XML
On the server side using XML is equally simple:import grails.converters.XMLdef showBook() {
def b = Book.get(params.id) render b as XML
}
<g:javascript> function updateBook(data) { var id = $(data).find("book").attr("id"); $("#book" + id + "_title").html( $(data).find("title").text() ); } </g:javascript> <g:remoteLink action="showBook" id="${book.id}" onSuccess="updateBook(data)"> Update Book </g:remoteLink> <g:set var="bookId">book${book.id}</g:set> <div id="${bookId}"> <div id="${bookId}_title">The Stand</div> </div>
Script Centric Ajax with JavaScript
Script centric Ajax involves actually sending JavaScript back that gets evaluated on the client. An example of this can be seen below:def showBook() { def b = Book.get(params.id) response.contentType = "text/javascript" String title = b.title.encodeAsJavaScript() render "$('#book${b.id}_title').html('${title}');" }
contentType
to text/javascript
. If you use Prototype on the client the returned JavaScript will automatically be evaluated due to this contentType
setting.Obviously in this case it is critical that you have an agreed client-side API as you don't want changes on the client breaking the server. This is one of the reasons Rails has something like RJS. Although Grails does not currently have a feature such as RJS there is a Dynamic JavaScript Plugin that offers similar capabilities.Responding to both Ajax and non-Ajax requests
It's straightforward to have the same Grails controller action handle both Ajax and non-Ajax requests. Grails adds theisXhr()
method to HttpServletRequest
which can be used to identify Ajax requests. For example you could render a page fragment using a template for Ajax requests or the full page for regular HTTP requests:def listBooks() { def books = Book.list(params) if (request.xhr) { render template: "bookTable", model: [books: books] } else { render view: "list", model: [books: books] } }