Update Table Data in Grails using Ajax Calls

Using Ajax for simple forms can offer users a very clean, simple and fast way to input data. I came across a situation recently where I was looking into replacing a document based workflow with an application. The documents themselves contained a series of different kinds of transactions that could have occurred. There were not a set number of any of the types and the user needed a simple way to enter many rows of data.

Grails offers some very easy to use simple Ajax controls. The formRemote tag has an update parameter that can be used to specify a DOM element to update after the form is submitted. This is Ajax in it’s simplest form. Submit some data and replace the contents of a DOM element with a partial-page update. This works well if you want to update a div for example. But what if you want to add a row to a table? In the standard update method, you would have to re-render the entire table contents. In many cases that will be fine, but I figured I could do better than that and just render the new row and add it to the table.

Defining Domain Classes

For this example we’ll start with some simple classes. An Account can have many Checks posted against it. There are no set number, so we define a hasMany relationship between the Account and the Checks.


class Account {
static transients = ['checksTotal']
static hasMany = [checks:Check]

Date date = new Date()

Double getChecksTotal() {
if (! checks)
return 0
return checks.inject(0) { current, check-> current + check.amount }
}

static mapping = {
checks joinTable: false
}
}

class Check {
String name
Double amount
String checkNumber
String reason
}

Creating a Controller

Next we need to create a Controller to mediate between our Domain and our Views. The Controller is setup to generate the default scaffold. We’ll end up overriding the show view to add a form on the page to easily post Checks to that Account. The action is the postCheck action. This is our Ajax action that will post the Check to the Account.


class AccountController {

def scaffold = true

def postCheck = {
def account = Account.get(params.id)
if(account) {
def check = new Check(params)
account.addToChecks(check)
if(! account.hasErrors() && account.save()) {
render template:'check', bean:check, var:'check'
}
}
}
}

The postCheck method calls the render method to render a template and return it as the Ajax response. This template contains the markup for a single Check row.

You can see the check template here:

${check?.name} ${check?.checkNumber} ${check?.reason}

Creating the Ajax Form

Now we need to add the form to our account/show.gsp so that we can call the AccountController.postCheck action. The example form is below. The thing to notice is that we’re not using the update parameter of the formRemote, but rather the onSuccess parameter. The update method tell the Ajax callback what element to replace but we can’t do that with a table. onSuccess on the other hand allows us to handle the returned values in our own way. Here’ we’re going to call the appendTableRow Javascript function to handle the response.

In this case I definitely don’t want to replace the entire node because the first row of my table is actually the form itself. This gives it a very nice look where the data is entered under the appropriate header and then immediately shows up as the following row when the user hits enter.

Checks


Name Check # Amount Reason


Luckily the appendTableRow function is made pretty easy by using the prototype APIs. The event returned to us is an HTML snippet, so in this case we just want to insert that snippet directly into the DOM which is accomplished with the insert prototype function.

function appendTableRow(tableId, e) {
$(tableId).down('tbody').down('tr').insert({after: e.responseText});
}

In the end you have a data table that allows for easy, fast updates with almost no hassle.

RESTful Rails for Ajax

Ruby on Rails 1.2 added full support for building RESTful services to the already nice web page support. REST is a conceptually simple idea, yet incredibly powerful. REST is a Web based API to an application. It builds on the basic building blocks of HTTP: URLs and HTTP Methods (think verbs).

A URL (Uniform Resource Locator) uniquely identifies a resources on the web. HTTP uses the concept of Methods to give context to a request to a URL. Most developers will be familiar with a GET and a POST. These methods are used to get a resource and to modify a resource respectively. But there are other http verbs as well. The two other interesting ones for a REST service are PUT and DELETE. Both of these are pretty self explanatory. PUT creates a resource at the remote location and DELETE removes one.

For Example:
GET
http://example.com/catalog/item/1

DELETE
http://example.com/catalog/item/1

Both of these use the same URL, but the HTTP Method means different things will happen.

Creating A RESTful API with Rails

Rails makes it easy to create a RESTful application. The same controllers can be used to render a web page and to provide a programmatic API to your application.

Rails provides a scaffold_resource generator that creates the skeleton of a resource driven application:

./script/generate scaffold_resource order

This creates Model, View and Controllers just like regular scaffold, but unlike scaffold, it adds some extra functionality.

class OrdersController < ApplicationController # GET /orders/1 # GET /orders/1.xml def show @order = Order.find(params[:id]) respond_to do |format| format.html # show.rhtml format.xml { render :xml => @order.to_xml }
end
end
end

Now if you request a path ending in .xml it will render the response as an XML document that can be consumed by another program.

Applying REST as an Ajax solution

The great news is that you can use this RESTful API directly as an API to use for building a highly-dynamic Ajax application. (See my post on using Ajax with PHP for an example). But what’s even cooler is that you can use the same technique to build a JSON API. JSON is much easier and less resource intensive to consume in an Ajax application than XML.

Changing your controller to support JSON ends up being really easy. All you have to do is add a single line in the respond_to block to support it:

class OrdersController < ApplicationController # GET /orders/1 # GET /orders/1.xml # GET /orders/1.js def show @order = Order.find(params[:id]) respond_to do |format| format.html # show.rhtml format.xml { render :xml => @order.to_xml }
format.js { render :json => @order.to_json }
end
end
end

Just like in the XML example, if you make a request that ends in .js then you will get a response rendered as JSON. Consuming that JSON Service with something like Dojo allows you to easily create a dynamic web application.


dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.date.*");
dojo.require("dojo.lfx.*");

function getOrder(id) {
dojo.io.bind({url: "/orders/" + id + ".js", handler: showOrder, mimetype: "text/json"});
}

function showOrder(type, data, evt) {
dojo.dom.removeChildren(dojo.byId('order'));
appendOrderPart('order_number', data.attributes.order_number);
appendOrderPart('time', data.attributes.time);
dojo.lfx.highlight(dojo.byId('order'), dojo.lfx.Color);
}
function appendOrderPart(id, value) {
var element = document.createElement("div");
element.id=id;
element.innerHTML=value;
dojo.byId('order').appendChild(element);
}
function init() {
getOrder(1);
}

dojo.addOnLoad(init);

Conclusion

With a few simple lines of code you can not only render a web page, you can also create an XML API and a JSON API. That’s what I call developer friendly!

Ajax with JSON using PHP and DOJO

Buzzword alert! Buzzword alert! Synergisticly expedite transparent web-readiness! Buzzword alert! Buzzword alert!

Ok, now that I’ve got that out of the way…

Ajax is a web application development architecture that resembles more of a client-server architecture than traditional web development. In an Ajax application a client application is delivered to the browser consisting of HTML, CSS and JavaScript. The interactions of the client with the server send and receive data, data that the client then knows how to display to the user.

While Ajax has an ‘X’ which stands for XML in its name, Ajax really has nothing to do with XML at its core. In reality parsing XML is usually a lot more work than you need to do when you expect that a client will be a browser. Along comes JSON. JavaScript Object Notation is a structured format that corresponds to the needs of the client-side programming environment: JavaScript. JSON can be evaluated on the client into JavaScript object graphs, no parsing, no XML Sax or DOM parsing, just eval() into a JavaScript object and then call methods on it.

Ajax, as a hot technology, I was of course interested in learning more so I created a small example application that I could build and play with a bit. I thought I’d share it with everyone so they could use it as a quick-start example for trying some of these technologies.

I chose to use the DOJO Toolkit as my client-side framework because it seems to have a very broad library already built and a reasonable amount of documentation. DOJO is really engineered like a true software application. It really shows off the fact that you can write good code and good frameworks using the JavaScript language.

Show Me Some Code

Here’s an example of a simple blog application that talks to a single table to display articles.

showArticle.html

A very simple HTML skeleton that imports the CSS, DOJO and the Application written in JavaScript.







    blog.js

    The Application that is delivered to the Client.

    getArticle() is called and initiates an asynchronous call to the getArticle.php code. When the response comes back DOJO automatically calls the showArticle() function and passes the response data to it. The showArticle() function handles formatting the data by manipulating the HTML DOM of the page.


    dojo.require("dojo.event.*");
    dojo.require("dojo.io.*");
    dojo.require("dojo.date.*");
    dojo.require("dojo.lfx.*");
    function getArticle(id) {
    var idStr = "{\"id\":" + id + "}";
    request = {'action' : 'getArticle', 'data' : idStr};
    dojo.io.bind({
    url: "getArticle.php",
    handler: showArticle,
    mimetype: "text/json",
    content: request
    });
    }
    function showArticle(type, data, evt) {
    dojo.dom.removeChildren(dojo.byId('article'));
    appendArticlePart('title', data.title);
    var date = dojo.date.fromSql(data.time);
    appendArticlePart('time', dojo.date.toRelativeString(date));
    appendArticlePart('content', data.content);
    dojo.lfx.highlight(dojo.byId('article'), dojo.lfx.Color);
    }
    function appendArticlePart(id, value) {
    var element = document.createElement("div");
    element.id=id;
    element.innerHTML=value;
    dojo.byId('article').appendChild(element);
    }

    getArticle.php

    The code that lives on the server and responds to a given service request. This PHP code parses the HTTP request that the DOJO toolkit sends to the server. It parses the data from a JSON string into PHP objects, calls into the database and gets some values out. It then turns a PHP array into a JSON string to return to the web client.

    decode($data);
    $article = getArticle($jsonArray);
    print $json->encode($article);
    }
    function getArticle($node) {
    $result = null;
    $link = connect_db();
    if ($stmt = $link->prepare("select id, title, publish_time, content from articles where id=?")) {
    $stmt->bind_param("i", intval($node->id));
    $stmt->execute();
    $stmt->bind_result($id, $title, $time, $content);
    if ($stmt->fetch()) {
    $result = array(
    "id"=> $id,
    "title" => $title,
    "time" => $time,
    "content" => $content,
    "objectId"=> "article"
    );
    }
    $stmt->close();
    }
    $link->close();
    return $result;
    }
    function connect_db() {
    $mysqli = new mysqli("localhost", "root", null, "blog");
    /* check connection */
    if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
    }
    return $mysqli;
    }
    ?>

    While this example is written in PHP, there is nothing that would prevent you from writing the server component in any language. There are JSON libraries for every language you’ve ever heard of (and a lot that you’ve never even heard of). The notation itself is fairly simple (it’s about 700 lines of code in PHP), so implementing it in another language should be relatively easy as well.

    Consider using implementation neutral URIs for your service calls and then using something like Apache mod-rewrite to map those URIs to the proper calls in whatever language you use to implement the server code. Doing this and you should be able to completely decouple your web client from the server components.

    Resources

    Ajax
    JSON
    PHP
    DOJO Toolkit
    JSON-PHP
    PHP-JSON
    Dojo: The Definitive Guide
    Mastering Dojo: JavaScript and Ajax Tools for Great Web Experiences (Pragmatic Programmers)

    RJS Templates for Rails

    I recently got a free copy of RJS Templates for Rails from the Milwaukee Ruby User’s Group. O’Reilly has a program that makes books available for free to Users Groups, which is a really nice thing (of course they bank on the word-of-mouth advertising that comes from it. Hi O’Reilly! ).

    RJS Templates for Rails is an O’Reilly “Short Cut” which is basically a small book released as a PDF only. It offers a brief look into some of the things that you can do with RJS templates that were added in Ruby on Rails 1.1. RJS is a way to write client-side JavaScript using the Ruby language and JavaScriptGenerator API. This allows you to do complex, multi-step processing to modify different parts of the page in a single request.

    The JavaScriptGenerator API is accessible from within a Controller and from RJS Templates. Which you use is part style and part pragmatic. For one-liners it is often just easier to write the code inline, reserving the RJS templates for more complex scripts.

    Inline code would look like:

    def hide_details
    render :update do |page|
    page[:details].hide
    end
    end

    Where an RJS template is automatically wrapped with the render :update block.

    page.insert_html :bottom, 'list', '

  • New Item At Bottom
  • '

    Both of these are simple examples of course, but they give you an idea of what’s going on. Each of these would generate JavaScript and send it back to the client where it would be executed in the browser. You can see that you do not have to write any JavaScript to use these techniques. The only thing that you have to do is to include the Prototype library in your pages using:

    <%= javascript_include_tag :defaults %>

    RJS Templates for Rails is a really quick read that does a good job of getting you started with using RJS and the JavaScriptGenerator API. It starts with a very simple example program that you can have up and running in a matter of minutes. It continues with a slightly more in-depth example of an application that really uses some of the more interesting aspects of RJS including multi-element page updates with a single request.

    The book offers a reference to the API that gives you a quick reference to the methods that you can use to program JavaScript in Ruby. Being a short book, it does not offer a slew of recipes that you would want from a more comprehensive book. This feels like an appetizer to me, giving me a taste of what’s available, whetting my appetite for more.

    In the abstract, RJS Templates for Rails actually offers some really good insight into how some people are doing AJAX with code generation techniques. Instead of writing JavaScript, they are creating APIs in their programming language of choice and then using code generation techniques to output the client-side code. While this style requires that the toolkit creator knows a great deal about the language being generated (JavaScript), it can encapsulate that knowledge so that others can leverage it without getting into the details. This is how the Google Web Toolkit (GWT) works as well for the Java camp. Prior to reading this book I don’t think I quite got what the big deal was, but now I see these frameworks really can do some incredible things for people who don’t want to “get their hands dirty” doing client-side development.

    If you’re an AJAX whiz, I’d doubt that this would offer a lot unless you just wanted to see another implementation and didn’t know a lot about Rails. But if you want to see how easy it could be to add some really interesting AJAX features to a Rails application, this can help you get started. You’ll almost definitely want to get a more comprehensive book to give you some more ideas on how to handle a broader range of situations.

    RJS Templates for Rails – Cody Fauser – ISBN: 0-596-52809-4

    P.S.
    The October 2006 issue of MacTech has a really good article on RJS as well. It covers some of the same basics that the PDF covers, using a few different examples.