The form
element provides meta-data that the FormActor
uses when it executes form handlers and sends output data to the ModelMap
.
The form
element contains the following:
Attribute/Element | Description |
---|---|
| Required. This is the Nucleus path of the form handler. |
| Required. The name of the |
| Required. This attribute defines the actor ID, and is used for actor ordering. |
| The variable name that can access form handler properties and exceptions. |
| By default, all form handler submissions require session confirmation numbers. This property is set to |
| This element defines actors that must be executed prior to the execution of the current actor. There can be multiple |
| This element defines actors that, if present, must be executed prior to the execution of the current actor. There can be multiple |
| This element defines each actor’s input. Actors can have multiple |
| This element defines each actor’s output. |
| By default, most form handler submissions use forwards. It is recommended that you use forwards instead of redirects. To enable redirects, you must set this attribute to |
The following is an example of a form element that adds a single item to an order:
<!-- This chain is used to add a single item to an order --> <actor-chain id="addItemToOrder" transaction="TX_SUPPORTS"> <form id="cartModifierFormHandler" name="/atg/commerce/order/purchase/ CartModifierFormHandler" var="cartModifierFormHandler" handle="addItemToOrder"> <input name="catalogRefIds" value="${param.catalogRefIds}"> <tag-converter class-name="atg.droplet.ArrayTagConverter"/> </input> <input name="productId" value="${param.productId}"/> <input name="quantity" value="${param.quantity}"/> <input name="locationId" value="${param.locationId}"/> <input name="siteId" value="${param.siteId}"/> <!-- optional giftlistId/giftlistItemId are set if the item is added from a giftlist --> <input name="giftlistId" value="${param.addToWishlist ? nucleus['/atg/userprofiling/Profile'].wishlist.repositoryId : param.giftlistId}"/> <input name="giftlistItemId" value="${param.giftlistItemId}"/> <input name="addItemToOrderErrorURL" value="/model/atg/commerce/order/ purchase/CartModifierActor/addItemToOrder-error"/> <input name="addItemToOrderSuccessURL" value="/model/atg/commerce/order/ purchase/CartModifierActor/addItemToOrder-success"/> </form> </actor-chain> <actor-chain id="addItemToOrder-error" transaction="TX_SUPPORTS"> <actor id="error" name="/atg/commerce/order/purchase/CartModifierActor" chain-id="error" return-model-var="model"> <output id="model" add-map-children="true" value="${model}"/> </actor> </actor-chain> <actor-chain id="addItemToOrder-success" transaction="TX_SUPPORTS"> </actor-chain> <actor-chain id="error" transaction="TX_SUPPORTS"> <component id="fh" name="/atg/commerce/order/purchase/CartModifierFormHandler" component-var="fh"> <output id="formError" name="formError" value="${fh.formError}"/> <output id="formExceptions" name="formExceptions" value="${fh.formExceptions}" filter-id="detailed"/> <!-- Did a concurrent update exception occur? --> <output id="concurrentUpdate" name="concurrentUpdate" value="${fh.concurrentUpdate}"/> <output id="order" name="order" value="${fh.concurrentUpdate ? fh.order : null}" filter-id="detailed"/> </component> </actor-chain>
By default, all form
elements define success and error chains. You can use XML combining to modify the default behavior of the chains. The following example shows what you would create to make a combined file that modifies the addItemToOrder-success
chain:
<actor-chain id="addItemToOrder-success"> <actor id="order" name="/atg/commerce/ShoppingCartActor" chain-id="summary" return-model-var="model"> <output id="model" add-map-children="true" value=${model}" /> </actor> </actor-chain>
The success or error URL, if present, is generally a REST URL that references another actor that generates the next page. Success and error URL are specified by the actor definition. Your success and error URLs should start with /model/atg
if you are forwarding. If you are doing a redirect, start your URLs with /rest/model/atg
. The FormActor
uses the use-forward
attribute. Note that it is better to use forwarding than redirection.
Form Handler Arrays
When using a JSP form, you can set the individual form array elements. For example, if you wanted to review each user and set their input field to be first name and last name:
<dsp:droplet name="/atg/dynamo/droplet/ForEach"> <dsp:param bean="MultiProfileAddFormHandler.users" name="array"/> <dsp:oparam name="output"> <dsp:input bean="MultiProfileAddFormHandler.users[param:index] firstName" type="text"/> <dsp:input bean="MultiProfileAddFormHandler.users[param:index] lastName" type="text"/> </dsp:oparam> </dsp:droplet>
When using a FormActor
, use the priority
attribute to initialize input array size before the array is populated if you are passing input arrays. For example:
<actor-chain id="addMultipleItemsToOrder" transaction="TX_SUPPORTS"> <form id="cartModifierFormHandler" name="/atg/commerce/order/purchase/CartModifierFormHandler" var="cartModifierFormHandler" handle="addMultipleItemsToOrder"> <input name="addItemCount" value="${param.addItemCount}" priority="1000" /> <input name="items[].catalogRefId" value="${objectParam.items[].catalogRefId}" array-size="${param.addItemCount}"/> <input name="items[].productId" value="${objectParam.items[].productId}" array-size="${param.addItemCount}"/> … </form> </actor-chain>
To set individual elements, use the [ ]
syntax, and pass in array-size
attributes for each input
array element.
When a form actor processes an input tag that contains [ ]
in the name
string, the input is treated as an input array. Based upon the array-size
, the FormActor
adds the index between the brackets, for example, [0]
or [Index]
. It then adds the form input
tag to the form
tag. Both the input
name
and value
can use the [ ]
syntax, with the index substituted for their attribute values.
In the following example, the first input
tag value uses an array property and the second input
tag passes in a scalar value:
<input name="currentList[].amount" value="${objectParam.cipiList[].amount}" priority="1" array-size="${param.addItemCount}"/> or <input name="currentList[].amount" value="25.00" priority="1" array-size="${param.addItemCount}"/>
Use tag converters to convert array inputs:
<input name="catalogRefIds" value="${param.catalogRefIds}"> <tag-converter class-name="atg.droplet.ArrayTagConverter"/> </input>
Example: Disabling Form Actor Dynamo Session Confirmation Numbers
Important: The following information is for use within development environments only. Dynamo session confirmation numbers provide session security and must be enabled in production environments.
By default, FormActors
use Dynamo Session Confirmation Numbers, _dynSessConf
, for method calls and setting property values. However, session confirmation numbers are not required for calls such as outputting properties of a component, a JSPActor
, or a DropletActor
. For detailed information on Dynamo Session Confirmation Numbers, refer to the Platform Programming Guide.
The following example shows how to disable session confirmation numbers for a FormActor
:
<actor-chain id="login" transaction="TX_SUPPORTS"> <form id="profileFormHandler-login" name="/atg/userprofiling/ProfileFormHandler" handle="login" var="profileFormHandler" requires-session-confirmation="false"> <input name="value.login" value="${param.login}" /> <input name="value.password" value="${param.password}" /> <input name="loginErrorURL" value="/rest/model/atg/userprofiling/ProfileActor/login-error"/> <input name="loginSuccessURL" value="/rest/model/atg/userprofiling/ProfileActor/login-success"/> </form> </actor-chain>
Note that the /atg/dynamo/service/actor/Configuration.enforceSessionConfirmation
flag can also be used to disable this requirement during development. Again, it is recommended that this flag is disabled only in your development environment.
Example: Form Error Handling
When a form handler encounters an error, it typically processes the error by adding a DropletException
to the form handler and forwarding to an error URL. The handle
method returns false
, indicating that a forward or redirect has occurred, and the actor-chain immediately terminates. Success or error URLS can be supplied to the form handler using the input
element. If the error URL has been defined to use another actor-chain, a new ModelMap
and ActorContext
is created to issue the response.
For example, to invoke the cartModifierActor
to pass an error URL that will re-render the Add Item to Order page if there is an error:
# /atg/commerce/order/purchase/cartModifierActor <actor-template default-chain-id="addItemToOrder"> <actor-chain id="addItemToOrder" transaction="TX_SUPPORTS"> <form id="cartModifierFormHandler" name="/atg/commerce/order/ purchase/CartModifierFormHandler" var="cartModifierFormHandler" handle="addItemToOrder"> <input name="catalogRefIds" value="${param.catalogRefIds}"> <tag-converter class-name="atg.droplet.ArrayTagConverter" /> </input> <input name="productId" value="${param.productId}" /> <input name="quantity" value="${param.quantity}" /> <input name="locationId" value="${param.locationId}" /> <input name="siteId" value="${param.siteId}"/> <input name="addItemToOrderErrorURL" value="/model/atg/commerce/order/ purchase/CartModifierActor/addItemToOrder-error"/> <input name="addItemToOrderSuccessURL" value="/model/atg/commerce/order/ purchase/CartModifierActor/addItemToOrder-success"/> </form> </actor-chain> <actor-chain id="addItemToOrder-error" transaction="TX_SUPPORTS"> <actor id="error" name="/atg/commerce/order/purchase/CartModifierActor" chain-id="error" return-model-var="model"> <output id="model" add-map-children="true" value="${model}" /> </actor> </actor-chain> <actor-chain id="addItemToOrder-success"> <actor id="order" name="/atg/commerce/ShoppingCartActor" chain-id="summary" return-model-var="model"> <output id="model" add-map-children="true" value=${model}" /> </actor> </actor-chain> <actor-chain id="error" transaction="TX_SUPPORTS"> <component id="fh" name="/atg/commerce/order/purchase/CartModifierFormHandler" component-var="fh"> <output id="formError" name="formError" value="${fh.formError}" /> <output id="formExceptions" name="formExceptions" value="${fh.formExceptions}" filter-id="detailed" /> <!-- Did a concurrent update exception occur? --> <output id="concurrentUpdate" name="concurrentUpdate" value="${fh.concurrentUpdate}" /> <output id="order" name="order" value="${fh.concurrentUpdate ? fh.order : null}" filter-id="detailed" /> </component> </actor-chain> </actor-template>
If the CartModifierFormHandler
encounters an error, the form handler identifies a formError
and forwards to the AddItemToOrderErrorURL
property in the CartModifierFormHandler
.
If there is no error, the detailed view of the order is displayed.
Error Code Response Types
Note that there are two types of error message patterns provided as a response. For Oracle Commerce Core Commerce-based form handlers, the error message response is similar to the following:
{
"formError":true,
"formExceptions":[{
"localizedMessage":"There was an error updating this order",
"cause":null,
}],
"concurrentUpdate":false
}
For Oracle Commerce Platform-based form handlers, the form handler response is similar to the following:
{"formError":true, "formExceptions":[{"localizedMessage":"The password and
login do not match","errorCode":"invalidPassword"}]}