It is very easy to create and manage Ajax calls in our framework. Just a few lines to write in your template file and your java class. For simple Ajax update of a component, you don't even have to write Javascript !

In your Java class

Our portlets can use specific ActionListeners to receive and process Ajax calls. To do that, you must create an inner static class named following this convention : action name followed by ActionListener

Example : (ParentClass being the class in which you are writing).

static public class SaveActionListener extends EventListener<ParentClass>

Don't forget to declare this listener in the configuration of your portlet, with this :

listeners = ParentClass.SaveActionListener.class

in the correct annotation (ComponentConfig, EventConfig, etc).

Inside this class, you will have to create an execute method like this :

public void execute(Event<ParentClass> event) throws Exception

This method is called every time the listener gets an event from the client, hence you can process this event in it, using the event attibute. Use it to get parameters from a form in your client, to modify the status of your portlet etc.

Possible ways to use the event attribute :

* String value = event.getRequestContext().getRequestParameter("name"); // to get a value from a form
* ParentClass parent = event.getSource(); // to get the parent object (the portlet that threw and caugth the event)
* UIMyComponent portal = parent.getAncestorOfType(UIMyComponent.class); // to get any node in the hierarchy of UIComponents
If your action has to update an element on your client's interface, you must call :

event.getRequestContext().addUIComponentToUpdateByAjax(uicomponent) ;

at the end of the execute method, with the target component in parameter (the component that will be updated). We will come back on this later in the documentation.

You must create one inner action listener class for each Ajax call you want to handle on this portlet. All these classes must be declared in the configuration annotations of the main class, otherwise you will get an error. This done, your portlet is ready to accept Ajax calls from your client.

In your template file

Your server being configured to receive Ajax calls, you must configure the client interface to make these calls.

In the groovy template file associated with your portlet class (ParentClass here), you just have to add :

uicomponent.event("YourOperation"); // YourOperation is the same as in the ActionListener class (Save in our example above)

in a groovy code block. The event function will create an url starting with javascript: so you have to make sure this code can be executed in your environment.

If your operation must update the content of a component, you have to make sure that the target component is well rendered. Basically, just type this :

uicomponent.renderChild(UITargetComponent.class) ;

in a groovy code block. UITargetComponent is the class of the component that will be updated when

event.getRequestContext().addUIComponentToUpdateByAjax(uicomponent) ;

is called. Hence, uicomponent must be of type UITargetComponent. If this component is not rendered by default, when the portlet loads, don't forget to set its rendered attribute to false :

mycomponent.setRendered(false);

in the constructor of your portlet.

How JavaScript works

All the javascript is managed by the file eXo.portal.PortalHttpRequest.js in the portal project.

In this class, you will find 4 functions/classes (detailed below) :

* PortletResponse
* PortalResponse
* AjaxRequest
* HttpResponseHandler
and 6 functions :
* ajaxGet // Calls doRequest with an url in GET mode
* ajaxPost // Calls doRequest with an url in POST mode
* doRequest // Creates the AjaxRequest and HttpResponseHandler objects, and lauches the request process
* ajaxAbort // Cancels the current request
* ajaxAsyncGetRequest // Allows to create and execute a sync or async GET request
* ajaxRedirect // A simple javascript redirection with window.location.href
that are the entry points of these classes. You shouldn't have to call explicitly these functions, since the template file and the portlet class manage everything.

PortletResponse

This class doesn't contain any method. On creation, it just gets the response elements from the xml returned by Ajax, and store them in the corresponding attributes :

* portletId
* portletTitle
* portletMode // View, Edit, Help or Config
* portletState // Decode, Render
* portletData // The updated data to put in the component
* script //The javascript code to update the component
* blocksToUpdate // An array containing the containers to update with this script

You can access these attributes just by calling them from your PortletResponse instance.

PortalResponse

Contains an array of PortletResponses (attribute portletResponses) and two other attributes :

* data // Data to update
* script // Javascript code to update

AjaxRequest

By far the most important class of this file. Wraps the XMLHttpRequest object with some functions and attributes, to make it easier to use. You can find the complete documentation here : http://www.ajaxtoolbox.com/request/documentation.php

HttpResponseHandler

This class provides methods to handle the Ajax response.

* executeScript // execute some javascript
* updateBlocks // update some html components
* ajaxTimeout // a function called when the timeout of the ajax call exceeds. Just cancel the request
* ajaxResponse // creates a PortalResponse object from the data from the Ajax request
* ajaxLoading  // shows the loading popup and mask layer

Portal Ajax Response Data Structure

{PortalResponse}
  |
  |--->{PortletResponse}
  |
  |--->{PortletResponse}
  |          |-->{portletId}
  |          |-->{portletTitle}
  |          |-->{portletMode}
  |          |-->{portletState}
  |          |
  |          |-->{Data}
  |          |      |
  |          |      |--->{BlockToUpdate}
  |          |      |         |-->{blockId}
  |          |      |         |-->{data}
  |          |      |
  |          |      |--->{BlockToUpdate}
  |          |--->{Script}
  |
  |--->{Data}
  |      |
  |      |--->{BlockToUpdate}
  |      |         |-->{blockId}
  |      |         |-->{data}
  |      |
  |      |--->{BlockToUpdate}
  |--->{Script}

Example : manage several popups

If you have several actions that need to appear in a popup, you can use this technique to manage the different popup windows easily :

  1. Create a UIPopupAction in your main portlet class :
addChild(UIPopupAction.class, null, null);
and render it in your template file :
uicomponent.renderChild(UIPopupAction.class) ;
By default, this just create an empty container (popup) that will receive the new content by Ajax.
  1. Get this component in your action listener class, and update its content :
UIPopupAction uiPopupAction = uiMainPortlet.getChild(UIPopupAction.class) ;
uiPopupAction.activate(UIReferencesList.class, 600) ;
// UIReferenceList is the component that will appear in the popup. You don't have to declare it in the main portlet class. The activate method takes care of the creation of the component, and its rendering in the popup window. See the javadoc for more information on this class.
  1. Make this component updatable by Ajax : event.getRequestContext().addUIComponentToUpdateByAjax(uiPopupAction) ;
For each component that you want to appear in a popup window, add a action listener class and repeat the steps above with the appropriate component type.

Creator: Philippe Aristote on 2007/08/19 21:58
Copyright (c) 2000-2009. Allright reserved - eXo platform SAS
1.6.13286