Ajax is a Web mechanism that allows Javascript running in a Web page to communicate back with its server to request additional information, which can then be used to update parts of the page dynamically. It's very handy for producing nice interactive effects such as autocompletion, status updates, and selective exposure of data. Fiz contains facilities that make it easy to use Ajax.

Overview: the server is in charge

In Fiz Ajax requests are handled in three phases. In the first phase, Javascript code running in the browser initiates a request. To do this it calls a Fiz method and specifies a URL (which can include query values) plus optional additional data. This launches an Ajax request back to the server. The request is asynchronous: the initiating Javascript code does not wait for the request to complete, and it does not handle the response. Most likely the request was initiated from within an event handler; the event handler completes and the browser goes about its business while the request is carried out in the background.

In the second phase, the request arrives at the server, where it is dispatched to a Java method. The code on the server has complete control over the handling of the request: it can choose among several actions such as modifying the HTML of the page or executing arbitrary Javascript code in the browser. Fiz packages up these actions into a response message that is returned to the browser.

In the third phase the browser receives the response from Fiz. The response is dispatched automatically to Fiz Javascript code in the browser, and the Fiz code carries out the actions that were specified by the server. The Javascript code that initiated the request is not involved at this point: the actions specified by the server carried out in the background by Fiz library code.

Thus the browser initiates Ajax requests but the server completely controls the outcomes. This approach moves most of the complexity to the server side, keeps the Javascript code on the browser as simple as possible, and gives the server maximum flexibility.

Initiating Ajax requests

There are three ways to arrange for an Ajax request to occur. The first two approaches are used in Java code on the server, and the third approach can be used in Javascript code you write for the browser:

URLs and dispatching: "ajax" prefix

Ajax URLs are dispatched to a Java method on the server just like other URLs; see URL Dispatching for details. For example, the URL blog/ajaxUpdate will be dispatched to a method named ajaxUpdate in an Interactor class named BlogInteractor. The method names for Ajax requests must always start with ajax. Fiz handles Ajax requests differently than other requests (for example, the response is packaged differently, and errors are reported differently), and Fiz depends on the ajax prefix to indicate that it should use Ajax handling.

Handling Ajax requests

The Java code that handles an Ajax request typically does not generate HTML like a normal page request would (any such HTML will be ignored by Fiz). Instead, the handler code requests one or more of the following actions to be performed by the browser:

Any number of actions may be requested; they will be executed in the order requested. None of the actions execute until the Ajax handler returns, at which point information about all of the actions is returned to the browser for execution.

When an Ajax handler is invoked the main dataset will contain the incoming data for the request, including both query values from the URL and additional data passed to the Fiz.Ajax constructor.

Passing complex data to/from the browser

If you need to pass a large amount of structured data from the server to the browser, the easiest way to do this is using Datasets. The Dataset method toJavascript will generate a Javascript object literal that represents the contents of the Dataset: nested datasets will be represented using nested objects or arrays of objects. For example:

Dataset d = new Dataset("name", "Alice",
        "phone", new Dataset("type", "home", "number", "650-496-8104"),
        "phone", new Dataset("type", "cell", "number", "408-733-9925"));
d.toJavascript()

--> {name: "Alice", phone: [{type: "home", number: "650-496-8104"},{type: "cell", number: "408-733-9925"}]}

Anything that can be represented as a Dataset can be converted to a Javascript literal in this way. You can then include this literal in Javascript code like this:

cr.evalJavascript(Template.expandRaw("var x = @1;", d.toJavascript()));
cr.evalJavascript(Template.expandRaw("x.setData(@1);", d.toJavascript()));

Note: you should use Template.expandRaw, not Template.expandJs for including the literal in Javascript code: toJavascript has already escaped any special characters in the data values, and its result uses Javascript characters such as " that must not be escaped.

You can also send structured data from the browser to the server in Ajax requests. To do this, pass an Object literal structure to the Fiz.Ajax constructor. This will result in the creation of a nested Dataset in the main dataset on the server. For example, the following code will create a nested Dataset in the main dataset named person with the same structure as Dataset d from above:

new Ajax({url: "blog/ajaxUpdate", data: {person: {
        name: "Alice",
        phone: [
            {type: "home", number: "650-496-8104"},
            {type: "cell", number: "408-733-9925"}
        ]}}});

Managing state: page properties

In many cases your Ajax handler will need access to state that was created when the page was first rendered. One approach is to include this state in the page and return it as data with the Ajax request. However, this approach is insecure: there is no guarantee that the browser will return the same state that you included in the page (an evil client can fabricate arbitrary Ajax requests). For example, if you passed the name of a database table this way, an evil client could generate and Ajax request with a different table name, potentially leaking sensitive information or corrupting your database.

The best way to handle state needed by the Ajax handlers is to use the Fiz page property mechanism. You can use the method ClientRequest.setPageProperty to store information when you first render a page; then, any subsequent Ajax request for that page can retrieve the saved information using ClientRequest.getPageProperty.

Error handling

If an error occurs during an Ajax request it can be handled in any of three ways: