Donnerstag, 24. Juli 2008

Grails, AJAX and Client Templates

Grails just gets better by the day for me. Experimenting with AJAX especially with dynamically updating parts of screen, I have come across following set of problems:

  • How to transfer the data?
  • How to render the data?
  • How to add more dynamic functions to dynamically loaded portions of the page?

My initial attempts included rendering HTML on the server and transferring the code to the client, and then replacing innerHTML of the loaded page. This worked  OK, until I also wanted to invoke Javascript functions after loading the HTML. Before I realized what was happeninng I ended up with loads of HTML Snippets on the Server and Javascript Spaghetti Nightmare all over the place.

After some research i came across TrimPath. TrimPath is a template engine written entirely in Javascript and therefore can run on the client. It is quite similar to technologies like Velocity, JSP, or ASP and uses a Javascript object graph as a context for the dynamic parts. 

Folllowing Setup has proven to work for me:

Include Trimpath Library and Templates in the root HTML

Trimpath is loaded from a single Javascript file, I used the GSP tag for this:


Each template (i.e. page parts which will be dynamically updated) I want to use, is embedded in a hidden div tag, and has an ID. To simplify this step, I created a custom Tag for this:
[...]

To further streamline the process I added a number of additional tags with abstract looping, conditions, "inline edit boxes" and the likes. Currently all of this code is built around the Yahoo UI (YUI) library. I plan to abstract this like the other Grails AJAX tags.

Create Base Mechanism to Render Templates and Reload Page Portions

Using the Yahoo UI Scoping and Layout mechanism and Trimpath Library the Javascript is a no brainer:

YAHOO.ST.editor.renderTemplate = function (templateId, contextObject){
   var template = TrimPath.processDOMTemplate(templateId, contextObject)  
   YAHOO.ST.global.layout.getUnitByPosition('center').body.firstChild.innerHTML = template
};

Thats it. 

Invoke the Reload
All which is left on the client side now is to get the data to render (called contextObject in the previously mentioned code) and decide which template to show (called templateId above). In my example it is done in an Yahoo AJAX callback passing the JSON response as the contextObject:

success: function(oResponse) {
   var oResults = eval("("+oResponse.responseText+")")
   YAHOO.ST.editor.renderTemplate('template_edit", oResults)
}        

Provide JSON data 

Grails provides the easiest possible way to provide JSON formatted results. Import the JSON format:

import grails.converters.JSON  

and then in the controller render the result like follows:

render returnMap as JSON    

Done!

I am still tinkering on how to distribute logic: Should the client only pull data and decide what to do with it, or should the server send code and invoke methods on the client? If the latter is the case, I would think that a RJS like extension for GRAILS would be desirable.

Grails, Javascript Templating and YahooUI make it so easy to create Rich Internet Applications by "pure programing", that it never ceases to amaze me. Keep up the good work!

Keine Kommentare: