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 !
Don't forget to declare this listener in the configuration of your portlet, with this :
in the correct annotation (ComponentConfig, EventConfig, etc).
Inside this class, you will have to create an execute method like this :
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 :
If your action has to update an element on your client's interface, you must call :
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 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 :
in a groovy code block. UITargetComponent is the class of the component that will be updated when
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 :
in the constructor of your portlet.
and 6 functions :
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.
You can access these attributes just by calling them from your PortletResponse instance.
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.
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.
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>
listeners = ParentClass.SaveActionListener.class
public void execute(Event<ParentClass> event) throws Exception
* 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
event.getRequestContext().addUIComponentToUpdateByAjax(uicomponent) ;
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)uicomponent.renderChild(UITargetComponent.class) ;
event.getRequestContext().addUIComponentToUpdateByAjax(uicomponent) ;
mycomponent.setRendered(false);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
* 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
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 scriptPortalResponse
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.phpHttpResponseHandler
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 :- Create a UIPopupAction in your main portlet class :
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.
- Get this component in your action listener class, and update its content :
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.
- Make this component updatable by Ajax : event.getRequestContext().addUIComponentToUpdateByAjax(uiPopupAction) ;
on 20/08/2007 at 07:08