4.4. First Ajax Example

In this first example we demonstrate how to handle Ajax requests with a DefaultAjaxBehavior. DefaultAjaxBehavior is the default implementation of the AjaxBehavior interface. Below is the Page class, AjaxBehaviorPage.java, showing a DefaultAjaxBehavior added to an ActionLink, called link with an HTML ID of link-id. The DefaultAjaxBehavior onAction method will be invoked to handle the Ajax request. The onAction method returns an ActionResult that is rendered to the browser.

public class AjaxBehaviorPage extends BorderPage {

    private static final long serialVersionUID = 1L;

    private ActionLink link = new ActionLink("link", "here");

    public AjaxBehaviorPage() {
        link.setId("link-id"); 1

        addControl(link);

        // Add a DefaultAjaxBehavior to the link. The DefaultAjaxBehavior will be invoked when the
        // link is clicked.
        link.addBehavior(new DefaultAjaxBehavior() { 2

            @Override
            public ActionResult onAction(Control source) { 3

                // Formatted date instance that will be added to the
                String now = format.currentDate("MMM, yyyy dd HH:MM:ss");

                String msg = "AjaxBehavior <tt>onAction()</tt> method invoked at: " + now;

                // Return an action result containing the message
                return new ActionResult(msg, ActionResult.HTML); 4
            }
        });
    }
} 
1

We assign to ActionLink the HTML ID: link-id. The ID will be used to identify the ActionLink as the Ajax target control. The client-side JavaScript code is expected to send this ID as an Ajax request parameter.

2

Next we add the DefaultAjaxBehavior to the ActionLink. Adding a Behavior to a control will also register that control with the ControlRegistry as a potential Ajax target control.

3

We also implement the DefaultAjaxBehavior onAction method in order to handle the Ajax request.

4

Finally we return an ActionResult containing some HTML content that is rendered to the browser.

Below we show the Page template ajax-behavior.htm, containing the client-side JavaScript code that will initiate the Ajax request.

Note: the example below uses the jQuery library, but any other library can be used. Also see the online Click examples for more Ajax demos.

<!-- // $link is a Velocity reference that will render an ActionLink at runtime. -->
Click $link to make an Ajax request to the server.

<div id="result">
    <!-- // Ajax response will be set here -->
</div>

<!-- // JavaScript code below -->

<!-- // Import the jQuery library -->
<script type="text/javascript" src="$context/js/jquery.js"></script>

<!-- // The client-side JavaScript for initiating an Ajax request -->
<script type="text/javascript">
    // This example uses jQuery for making Ajax requests:

    // Register a function that is invoked as soon as the entire DOM has been loaded
    jQuery(document).ready(function() { 1

        // Register a 'click' handler that makes an Ajax request
        jQuery("#link-id").click(function(event){
            // Make ajax request
            makeRequest();

            // Prevent the default browser behavior of navigating to the link
            return false;
        })
    })

    function makeRequest() {
        // Get a reference to the link
        var link = jQuery('#link-id');

        // In order for Click to identify the Ajax target, we pass the link ID
        // attribute as request parameters
        var extraData = link.attr('id') + '=1'; 2

        // The Ajax URL is set to the link 'href' URL which contains all the link default parameters,
        // including it's name/value pair: 'actionLink=link'
        var url = link.attr('href'); 3

        jQuery.get(url, extraData, function(data) {
            // 'data' is the response returned by the server

            // Find the div element with the id "result", and set its content to the server response
            jQuery("#result").html("<p>" + data + "</p>"); 4
        });
    }
</script> 
1

We start off with a jQuery ready function that is executed as soon as the browser DOM has been loaded. This ensures that the function body is executed before the page images are downloaded, which results in a more responsive UI.

2

This is an important step. We need to pass the link's HTML ID attribute as request parameters in order for the server to identify which server-side control is the Ajax target. We use the jQuery attr function to lookup the link's HTML ID attribute. Click doesn't actually use the value of the parameter, it is enough that the name is present. In this example we pass a value of 1, but any other value could be used, or even left out.

3

This is another important step. In addition to the ActionLink HTML ID pararameter, we also need to send the link's href parameters, otherwise the ActionLink onProcess method won't fire the AjaxBehavior onAction event. An easy way to achieve this to set the Ajax URL to the ActionLink href value.

4

Finally we the jQuery html function to update the div content with the server response.

4.4.1. Ajax Trace Log

Looking at the output log we see the following trace:

[Click] [debug] GET http://localhost:8080/mycorp/ajax/ajax-behavior.htm
[Click] [trace]    is Ajax requesttrue
[Click] [trace]    request param: actionLink=link
[Click] [trace]    request param: link-id=1
[Click] [trace]    invoked: AjaxBehaviorPage.<<init>>
[Click] [trace]    invoked: AjaxBehaviorPage.onSecurityCheck() : true
[Click] [trace]    invoked: AjaxBehaviorPage.onInit()
[Click] [trace]    invoked: 'link' ActionLink.onInit()
[Click] [trace]    the following controls have been registered as potential Ajax targets:
[Click] [trace]       ActionLink: name='link'
[Click] [trace]    invoked: 'link' ActionLink.isAjaxTarget() : true (Ajax target control found)
[Click] [trace]    invoked: 'link' ActionLink.onProcess() : true
[Click] [trace]    processing AjaxBehaviors for control: 'link' ActionLink
[Click] [trace]       invoked: AjaxBehaviorPage.1.isRequestTarget() : true
[Click] [trace]       invoked: AjaxBehaviorPage.1.onAction() : ActionResult (ActionResult will be rendered)
[Click] [info ]    renderActionResult (text/html) - 1 ms
[Click] [trace]    invoked: 'link' ActionLink.onDestroy()
[Click] [trace]    invoked: AjaxBehaviorPage.onDestroy()
[Click] [info ] handleRequest:  /ajax/ajax-behavior.htm - 25 ms

First thing we notice is that the request is recognized as an Ajax request.

We can also see from the log that the Ajax request passed the parameters, link-id=1 and actionLink=link to the server. link-id is the ActionLink HTML ID attribute that will be used to identify the Control as the Ajax request target.

Next, the log prints which controls have been registered as potential Ajax targets. In our example we added an AjaxBehavior to the ActionLink so the ActionLink is registered as an Ajax target.

Next, the ActionLink#isAjaxTarget was invoked and because it returned true, ActionLink will be used as the Ajax target control.

Having found the Ajax target, the ActionLink onProcess is called.

Next, the log shows it found the target AjaxBehavior by invoking the AjaxBehavior#isRequestTarget method, which returned true.

The AjaxBehavior#onAction is invoked which returns an ActionResult.

Finally, the ActionResult is rendered to the browser.

4.4.2. Ajax Trace Log - No Ajax Target Control Found

Below we show a log trace where no Ajax target control is found. The most common reason this can occur is if the JavaScript code that initiates the Ajax request does not send the necessary request parameters to identify the Ajax target control. Another problem is if no Control is registered ith the ControlRegistry, thus there is no potential Ajax target control. This can occur if no Behavior is added to a Control.

[Click] [debug] GET http://localhost:8080/mycorp/ajax/ajax-behavior.htm
[Click] [trace]    is Ajax requesttrue
[Click] [trace]    request param: actionLink=link
[Click] [trace]    invoked: AjaxBehaviorPage.<<init>>
[Click] [trace]    invoked: AjaxBehaviorPage.onSecurityCheck() : true
[Click] [trace]    invoked: AjaxBehaviorPage.onInit()
[Click] [trace]    invoked: 'link' ActionLink.onInit()
[Click] [trace]    the following controls have been registered as potential Ajax targets:
[Click] [trace]       ActionLink: name='link'
[Click] [trace]    *no* target control was found for the Ajax request
[Click] [trace]    invoked: 'link' ActionLink.onDestroy()
[Click] [trace]    invoked: AjaxBehaviorPage.onDestroy()
[Click] [info ] handleRequest:  /ajax/ajax-behavior.htm - 87 ms

Notice from the log that the only request parameters sent is actionLink=link.

Next, the log prints which controls have been registered as potential Ajax targets. In our example we added an AjaxBehavior to the ActionLink so the ActionLink is registered as an Ajax target.

Finally, we see that *no* Ajax target control was found. This is because the ActionLink ID attribute, link-id, does not match the incoming request parameter, actionLink=link, hence the ActionLink was not identified as the Ajax request target and no response is rendered.

4.4.3. Ajax Trace Log - No Target AjaxBehavior Found

Below we show a log trace where no target AjaxBehavior is found. This can occur if no AjaxBehavior's isRequestTarget returns true.

[Click] [debug] GET http://localhost:9999/mycorp/ajax/ajax-behavior.htm
[Click] [trace]    is Ajax requesttrue
[Click] [trace]    request param: actionLink=link
[Click] [trace]    request param: link-id=1
[Click] [trace]    invoked: AjaxBehaviorPage.<<init>>
[Click] [trace]    invoked: AjaxBehaviorPage.onSecurityCheck() : true
[Click] [trace]    invoked: AjaxBehaviorPage.onInit()
[Click] [trace]    invoked: 'link' ActionLink.onInit()
[Click] [trace]    the following controls have been registered as potential Ajax targets:
[Click] [trace]       ActionLink: name='link'
[Click] [trace]    invoked: 'link' ActionLink.isAjaxTarget() : true (Ajax target control found)
[Click] [trace]    invoked: 'link' ActionLink.onProcess() : true
[Click] [trace]    processing AjaxBehaviors for control: 'link' ActionLink
[Click] [trace]       invoked: AjaxBehaviorPage.1.isRequestTarget() : false
[Click] [trace]    *no* target AjaxBehavior found for 'link' ActionLink - invoking AjaxBehavior.isRequestTarget() returned false for all AjaxBehaviors
[Click] [trace]    invoked: 'link' ActionLink.onDestroy()
[Click] [trace]    invoked: AjaxBehaviorPage.onDestroy()
[Click] [info ] handleRequest:  /ajax/ajax-behavior.htm - 80 ms
      

We can see from the log that the Ajax request sent the parameters, link-id=1 and actionLink=link to the server.

Next we notice that the AjaxBehavior isRequestTarget() returned false.

Finally we see that *no* target AjaxBehavior was found for the Ajax target control, 'link' ActionLink.