OpenWGA 7.6 - OpenWGA Concepts and Features

Design and development » WebTML » Features » Actions

Creating controls to call actions

To call an action from a WebTML page some page control must be created that the user can interact with to trigger the action. This control is also often called the action link.

Some examples of functionalities that create an action link for HTML pages:

  • An Action link URL created via <tml:url action="id">
  • A HTML button created via <tml:button clickaction="id">
  • A form input of type "select/radio/checkbox/boolean" which calls the action when the value selection changes, created via <tml:input changeaction="id">
  • A form that calls an WebTML action on normal form submit, created by <tml:form defaultaction="id"/>
  • Some clientside JavaScript code calling WGA.callAction(actionLink) with an action link created by <tml:action ref="id"/>

All WebTML tags that create action links need the tag <tml:htmlhead> embedded to the HTML pages head section or the action link may not work.

Common among all these functionalities is that they receive the ID of the action to call. See previous chapter Ways of defining actions on what ID an action has dependent on its definition.

When an action link is called the following happens:

  • The browser either fetches the action link URL or, if the link was defined inside a WebTML form, posts the WebTML form data so it is available to the action and the following request
  • The action code is processed. The script uses the document context of the WebTML tag that created the action link as base context
  • After the action is finished the same WebTML page is rendered again, unless a redirection was triggered in the action using method WGA.redirectTo()
    • If the action link was rendered inside a WebTML portlet then only the WebTML portlet that contained the action link is reloaded using AJAX (unless deactivated)

Action parameters

It is possible to pass parameters to a WebTML action.

Parameters for action links are defined at the tag that creates the action link via attributes param1...param5. Only string values are allowed as parameters. The action receives action parameters as WebTML variables tmlparam1 to tmlparam5. See the following example of an action that sets a field on a TMLForm and uses parameters to determine the field and its value:

<tml:action id="storeField">

tmlform.setField(tmlparam1tmlparam2);
</tml.action>


<tml:url action="storeField" param1="fieldName" param2="fieldValue"/>

An alternative to using those WebTML variables there also is a list actionParams available which lists the given parameters, with the param at index 0 matching "param1":

<tml:action id="storeField">
tmlform.setField(actionParams.get(0)actionParams.get(1));
</tml.action>

<tml:url action="storeField" param1="fieldName" param2="fieldValue"/>

It is recommended to use "actionParams" in favor of the "tmlparam..." variables if action calls are to be cascaded. An action may internally use method WGA.callAction() to call another action. This inner action now may overwrite the variables tmlparam... with its parameter values. As variables are shared among the actions this will also overwrite those variables for the calling action, effectively losing the initially passed values for it. The list "actionParams" is safe from this overwriting effect and will keep the initial params.

Action context

Action scripts normally use the context of the tag that created the action link as base context. So if you generate action links inside an content iteration tag like <tml:navigator> or <tml:foreach type="content"> then the actions that they trigger will have access to the current document of the iteration as base context:

See the following example where a button triggers an action that adds the key of the current iteration document to a "favorites" list on the user profile:

<tml:action id="addToFavorites">

var favs = profile.itemList("favorites");

favs.add(STRUCTKEY);

profile.setItem("favorites", favs);

profile.save();

</tml:action>


<ul>

<tml:navigator type="children">
    <li><tml:link/> <tml:button clickaction="addToFavorites">Add to favorites</tml:button>

</tml:navigator>

</ul>

The button which calls the action is generated inside <tml:navigator> so one individual button is put out for each document that the navigator iterates over. The action of each of these buttons is executed under the context of the individual document for which it was generated. So the action just retrieves the key of the current context document to add it to its favorites list.

Because of this behaviour it is generally not neccessary to manually pass any information about the current context to the action.

An exception to this rule are documents that are retrieved from some data sources via query. Depending on the type of data source and query OpenWGA is not able to re-retrieve the "document" behind it, because it is merely a virtual pointer to an otherwise temporary query result row. The action then runs on a dummy context of the data source.

Calling from within TMLScript

WebTML actions can also be called from within any TMLScript code using method WGA.callAction():

WGA.callAction("myAction1");


Actions that are called that way are also able to receive parameters that are no strings. The parameters are just added to the method as additional method arguments:

WGA.callAction("myAction1", param1, param2, param3);


The actions that are available inside TMLScript of course depends strongly on the type of script. A script on a WebTML page can call all actions that were defined for the current user, including those defined on (already rendered) pages via <tml:action>. This is also possible inside other actions called from a WebTML page. If the current script has no access to a browser session - for example a scheduler job, a WebTML validation script or a content type event script - then those actions are not available, but TMLScript modules still are.

Calling from client side JavaScript

JavaScript running in the browser can also call WebTML actions. All WebTML pages which render <tml:htmlhead> can use the following built-in JavaScript functions to do this:

Both functions receive a single argument in form of a JavaScript object. This object contains all parameters for the action call as properties. The most important one, and mandatory on both functions, is "action":

WGA.action(

  { action: "<tml:action ref="myAction"/>" }

);

The action property takes an action link, generated by WebTML tag <tml:action>. Its ref attribute determines the action to call. Note the string delimiters around <tml:action>. They are necessary so the output of the WebTML tag will be evaluated as string  in JavaScript. This will get clear when seeing what is actually generated by <tml:action> and then sent to the browser:

WGA.action(

{ action: "##NULL##/4e453b3ffeae0f765dc35d415e99fd11/L4b_HWioetlYsODYD6TYQwzSgcNK2QCHLnJRQfH4ZC-_16e9ukM4j52jfaqEdgtF4EnQ0jys9Q-9PVCe6WI6iX7brAseVq17tTQ6zet2u9m6OUA9wfXrA999GWNBRcYRYNApcAE0pkngGbuJFqD5-RBVaj7Z3fsrO9qv17cLh4GMM7u-Ms7WIDjMi0L4cB1taSqUj_KhZd8Kihk-URvMVGyS2Pe4d6DxXNuONqLNAFd3aob90Msdysp_bme-ORCAKbq6QzFf3TM=" }

);

When using WGA.ajax.action() the <tml:action> tag must also specify attribute ajax="true".

WGA.ajax.action(

   { action: "<tml:action ref="myAction" ajax="true"/>" }

);

The parameter object of WGA.ajax.action() supports some properties to configure and tweak the AJAX behaviour. See the reference for details.

Specifying parameters from JavaScript

Optionally the param1...param5 attributes on <tml:action> can be used to determine WebTML action parameters for this action call.

WGA.action(

{ action: '<tml:action ref="myAction" param1="myParam"/>' }

);

However, when calling a WebTML action from clientside JavaScript this seldomly does what is really wanted. WebTML action parameters need to be determined on the serverside, like in this case is done by the <tml:action> tag. But most of the time when you call a WebTML action from clientside JavaScript you instead want to determine the values of its parameters also on the clientside.

There are two ways to provide clientside parameters to WebTML actions:

Use WebTML form fields as parameters

If you generate your action call inside a WebTML form then the action call will include the form data. This data then will be available to the WebTML form as "tmlform" object. So all data which your clientside JavaScript sets into the fields of the WebTML form will also be available to the action. If you already use a WebTML form this may be the easiest way to transport clientside parameters. Just add a hidden field to your form, and set its value just before you call the action. See the following example:

<tml:form id="theForm">


  <tml:input type="hidden" name="jsparam"/>


  <script>

    function callTheAction(theParam) {

      document.forms[0].elements['jsparam'].value = theParam;

      WGA.action( { action: '<tml:action ref="myAction'/>' } );

    }

  </script>


</tml:form>

The JavaScript function "callTheAction" first sets a value into the hidden input field "jsparam" of the HTML form (assuming that there is only one), then calls the action. When <tml:action> is rendered somewhere inside <tml:form> it automatically sends the form data along with the action call. If it is outside you can still tell it to send the form by using the form attribute.

On the serverside the action script can simply read the value of this field from the "tmlform" object:

var theParam = tmlform.jsparam;

Use URL parameters

Both functions WGA.action() and WGA.ajax.action() support adding URL parameters to the action call. You can do this by simply adding a property "params" to the function parameter object. The property itself should hold another JavaScript object whose properties become URL parameters on the action call:

WGA.ajax.action(

  {

    action: "<tml:action ref="myAction" ajax="true"/>",

    params: {

      key: theKey,

      title: "Hello World!",

      position: 5

    }

  }

);

The action call will have URL parameters "key", "title" and "position". The values of the properties will become the URL parameter values. Obviously you can pass on JavaScript variables here, like done with "theKey" in the example. You can also specify Non-String parameters, but be aware that they will automatically get converted to strings when they become URL parameters.

The called action can retrieve those URL parameters by using the method "getParameter()" on the this.request object in TMLScript:

var key = request.getParameter("key");

var title = request.getParameter("title");

var position = parseInt(request.getParameter("position"));

Note how we convert back the "position" parameter to a integer value.

Note that URL parameters are unsafe compared to WebTML action parameters. While the latter ones are encrypted and therefore unmodifiable as well as unreadable for the user URL parameters are not. They are always transmitted in cleartext and may easily be modified by the user. Do not depend the security of your app on the integrity of URL parameter values!

Calling as remote action

A special use case is calling actions remotely from a completely different process. This is called remote action and described in a separate chapter.