6. Ajax

6.1. Ajax using Callable Actions

Portlets can be Ajax-enabled by using Callable Actions (see “Callable Actions” (Section 2.2.9)). Each Callable Action can contain multiple Pluggable Actions which are used to perform the desired actions. By using specialized Pluggable Actions, namely the PlainCallableActionResponseAction (see Section 2.2.8.19, “PlainCallableActionResponseAction”) and the JsonCallableActionResponseAction (see Section 2.2.8.16, “JsonCallableActionResponseAction”), the response to the client is constructed.

Using a client-side JavaScript framework such as jQuery, existing View portlets can be easily extended to use Ajax functionality. For examples using Callable Actions to provide features like autocompletion, see the SDK portal.

6.2. Ajax using JSR 286

Custom portlets can be Ajax-enabled by using the new serveResource() method defined in the JSR 286 standard. Using resource URLs, portlets can return arbitrary data to the client, which can be used by client-side JavaScript frameworks. For an example on how resource serving may be used see the ServeResourceExample from the advanced examples page in Gentics Portal.Node SDK.

6.3. AJAX enabled requests to the Server

Besides specially implemented portlets that use AJAX functionality, it is also possible to enhance the overall user experience of the portal implementation by using AJAX enabled requests to the portal server. The main idea is to avoid full page reloads for every single click into a portlet (or into the portlet's frame), but to issue AJAX requests to the server instead and let the AJAX framework just replace the new rendered portlets in the portal page. This feature is called "Portlet Reloading" and will be described later in detail. Another example of AJAX enabled requests is "Portlet Drag & Drop", which even goes a step further: Here, part of the implementation (reordering the portlets on the portal page) is done on the client side, and only the result sent to the server as AJAX request (which again might lead to some portlets be re-rendered).

Any portal URL can be made AJAX enabled, by simply adding the parameter gentics.rl = true . The only difference to a non-AJAX enabled request is the format of the response. For a "normal" request, the response will always be the fully rendered portal page. The response format of an AJAx enabled request is described in the next section.

6.3.1. Response Format of AJAX enabled requests API

The response of an AJAX enabled request is a JSON object of the following structure:

Table 4.155. Portlet Reload Response Structure

NameTypeDescription
*ArrayAn array of JSON objects.
element in *JSON ObjectA single result object.
element.functionNameString The name of the JavaScript function which should be called. See “Replace rendered portlets API” (Section 6.3.3.3.3) for the function names, which are used for portlet reloading.
element.parametersJSON ObjectThe parameters for the function.

6.3.2. Response of AJAX enabled requests with an invalid session

When an AJAX enabled request is done with an invalid session cookie (e.g. when the session timed out), the response to this request cannot be what the user will expect. In such a case, the response will only contain the single function call to the client side function named GENTICS.invalidSession which should be implemented appropriately.

A basic implementation of this function would for example simply call location.reload(); to reload the whole page, such that the user can continue browsing the portal with the new session.

Additionally, EVERY request to the Portal to a new Session (i.e. with invalid or no session cookie) will result in a response that contains the header "X-Gentics: NEWSESSION".

6.3.3. Portlet Reloading

Portlet reloading enables the use of AJAX requests to selectively reload portlets without the need of a full-page reload. It does so by replacing the default link and submit actions by JavaScript methods, which submit the data to the portal server and interpret the response. Please note that portlet reloading only works together with portal pages (see “Portal Pages Implementation” (Section 14)). Portlet reloading is fully backwards-compatible and will fall back to the default behaviour (full-page reload) if JavaScript is disabled or unavailable on the client.

The portal server will try to detect, which portlets actually have changed their state upon an AJAX request and will render them. The algorithm is very similar to the automatic clearing of portlet caches in a "normal" (non AJAX) render-, action- or resource-request.

[Note]Note
It is important to keep in mind, that the change detection of portlets fail, when portlets have dependencies to other portlets e.g. by reading properties of them. The change detection only works, when properties of portlets are actively changed.
[Note]Note
Portlet reloading should not be enabled for portlets using the downloadcomponent in views (like the AdministrationPortlet). The downloadcomponent will not work properly when used in conjunction with portlet reloading. See Section 2.2.7.3.3, “DownloadComponent” for details on the downloadcomponent.
6.3.3.1. Parameters

Portlet reloading can be enabled portal-wide using portal parameters (see “Portlet Reloading” (Section 8.2.17)) or selectively for specific portlets using pnode parameters (see “Parameters of all Gentics Portlets” (Section 2.3)). For portal parameters use key "portal", for pnode parameters use "gentics".

Setting [gentics|portal].portletreload to true enables portlet reloading. To have the client-side script replace the standard links, set [gentics|portal].portletreload.replacelink to true. To also handle form submits by AJAX, set [gentics|portal].portletreload.replaceform to true. Which links and forms are replaced is defined by the [gentics|portal].portletreload.allclasses and the [gentics|portal].portletreload.replaceclasses parameters. If [gentics|portal].portletreload.allclasses is set to true, all elements are replaced. [gentics|portal].portletreload.replaceclasses can contain a comma-separated list of CSS classes, which define the elements to replace (i.e. the element must have at least one of the specified CSS classes to be replaced).

6.3.3.2. Templates

To use portlet reloading, several templates must be adapted.

6.3.3.2.1. Portal Page Template

The portal page template (see Section 14.1, “Portal Page Templates”) must include the necessary JavaScript files (see the SDK Portal for an example). The HTML element surrounding a portlet position must have a CSS class in the form gentics-portletreload-position-[positionid].

Example 4.43. Portal Page Template Example

...
<ul class="gentics-portletreload-position-left">
	#foreach($portlet in $portal.page.positions.left.portlets)
		$portlet
	#end
</ul>
...
								
6.3.3.2.2. Portlet Frame Template

In the portlet frame template (see “Portlet Frame Templates” (Section 14.2)), the outermost HTML element must have specific CSS classes, which have to be included using $portlet.portletreload (see the portlet frame template in the SDK portal for an example).

Example 4.44. Portlet Frame Template Example

<li class="$portlet.portletreload">
...
</li>
								

Additionally, it is necessary to define a portlet frame template for invisible portlets, that renders an invisible placeholder with the css classes.

Example 4.45. Portlet Frame Template Example for invisible portlets

<li class="$portlet.portletreload" style="display:none">
</li>
								
6.3.3.3. Client-side scripting

This section describes, how the Gentics Portal.Node APIs for the JSON response to AJAX enables calls can be used to implement Javascript methods to dynamically replace portlets in the browsers DOM tree with new versions. Based on this description you can either use the example implementation of the Gentics Portal.Node SDK Demo Portal, or implement it on your own.

Client-side scripting consists of three parts:

  1. Automatic modification of URLs to be AJAX enabled and using them in AJAX calls
  2. Generic handling of the response and calling the specified javascript methods
  3. Implementation of the portlet-reloading specific javascript functions (substitution of an already rendered portlet with a new version or adding a portlet to a position)

6.3.3.3.1.  Automatic modification of URLs to be AJAX enabled

For all rendered portlets that have the portletreload feature activated, the AJAX framework must bind callback functions that will automatically make AJAX requests whenever a link is clicked or a form is submitted from this portlet. The Gentics Portal.Node SDK Demo Portal contains an example implementation of this in the file gentics-portletreload.js (method GENTICS.PortletReload.replaceAjaxReloadUrls ). When javascript is not available in the browser, the links and forms will not be AJAX enabled and will still work as expected. 
show gentics-portletreload.js
show gentics-portletreload.js

6.3.3.3.2. Generic handling of the response

The JSON response of an AJAX enabled request must be interpreted and all specified javascript functions must be called. The Gentics Portal.Node SDK Demo Portal contains an example implementation for this in the file gentics-ajax.js (method GENTICS.processResult). 
show gentics-ajax.js
show gentics-ajax.js

6.3.3.3.3. Replace rendered portlets API

To render portlets in a specific position, the javascript function GENTICS.PortletReload.renderPortlet must be implemented. It will get the following parameters (as javascript object):

  • portletId id of the portlet
  • portletPosition id of the position in which the portlet needs to be rendered
  • portletPositionIndex index of the portlet in the position (starting with 0). Note that also invisible portlets will consume an index number, when contained in the position.
  • portletContent sourcecode of the rendered portlet (including the portlet frame).

The Gentics Portal.Node SDK Demo Portal contains an example implementation for this method in the file gentics-portletreload.js . 
show gentics-portletreload.js
show gentics-portletreload.js

6.3.3.4. Restrictions and common pitfalls

  • Portlet reloading should not be activated for a specific portlet (or link/form) when triggering this link/submitting this form will do one of the following:

    1. Login or logout the user
    2. Change the current portal page
    3. Change the visibility of portlets

  • Portlet reloading will not render any part of a portal page template again, but only single portlets (with their frames). So if the portal page template itself contains dynamic code depending on the current status of portlets, it is necessary to have URLs that might possibly change the state of portlets that influence the rendering of the portal page to be "normal" URLs (not AJAX enabled). The portal server has no means to automatically detect such situations, so this must be handled in the implementation appropriately!
  • Disabling portlet reloading for a single portlet does not prevent this portlet to be reloaded (e.g. by URLs to other portlets), but only prevents the URLs of this portlet to be AJAX enabled.

    Example: portlet A has portlet reloading activated and portlet B has portlet reloading not activated. Clicking an URL in portlet A might somehow modify the current status of portlet B as well, so both portlets would need to be re-rendered.

    This especially means that ALL portlets (no matter, whether they have portlet reloading activated or not) should be rendered using portlet frame templates with the necessary css classes (see “Portlet Frame Template” (Section 6.3.3.2.2) ), and ALL positions should also have the necessary css classes (see “Portal Page Template” (Section 6.3.3.2.1) ).

6.3.3.5. Disabling it for single button

Sometimes it is necessary to disable portlet reloading for only a single button. For example if it switches portlet pages or similar. To achive this, the following javascript code has to be executed prior to the form submit:

GENTICS.PortletReload.disabled = true

The default ButtonComponent template will add an onclick event to the button which executes the above statement if the component property "portal.portletreload" is set to "false".

6.3.4. Portlet Drag & Drop

Using a JavaScript framework, drag&drop for portlets can be implemented. Using a special Portal Action URL (available in the portal page template as $portal.portletpositionchange ), the new positions of the portlets are transfered to the server (see Gentics Portal.Node SDK Demo Portal for an example and “Customizing portlet positions by URL” (Section 14.3.2) for details).