Tuesday, November 15, 2005

Backbase and Forms

There was a discussion on the Backbase developer forums recently about how forms work. I found the manual a bit confusing and Laurens Holst from Backbase cleared things up. This post outlines what I learnt - hopefully I got it right.

Backbase can handle normal HTML forms where the submit causes the browser to go to another page with the form data is passed as query parameters or POST data depending on the form method. In this case the form looks and works exactly like a normal HTML form (See form1.html for a live example):
<form name="main" action="action1.yaws" method="post">
<table>
<tr>
<td>Name</td>
<td><input name="name" type="text" size="40"/></td>
</tr>
<tr>
<td>Data</td>
<td><textarea name="data"/></td>
</tr>
</table>
<input type="submit" value="Send"/>
</form>

For the submit button you can use 'input' with a type of 'submit', or the HTML 'button' element. They work the same way (form1a.html uses the button element).

The 'type' of an input defaults 'text' and the type of a button is supposed to default to 'submit' but this is not always the case cross browser. Laurens advised on the backbase forums to always specify the type explicitly if you are using the standard HTML elements. For example, some versions of Internet Explorer do not default a 'button' to be 'submit.

Backbase also provides an extension element called 'b:button'. This produces a button that is styled to look the same no matter what browser is used. The standard HTML buttons can look different across browser. Using 'b:button' requires slightly different attributes to the standard input or button type.

It uses two attributes. The first, b:action, is used to define what should happen when the button is pressed. For form submission we'd use 'submit'. You could load another file with 'load' or display an alert with 'alert'. There are many actions that can be used and they are covered in the BXML reference manual.

When the action is 'submit', a second attribute is required. This is b:target. It should be set to an XPath expression identifying which form will be submitted. Usually it's the parent form. You can use a relative path expression (like "../../form") or one indexed by the elements id (for example, "id('mainform')"). Another option is the XPath expression "ancestor::form[1]". This is better than "../../form" as it ensures you get the parent form no matter how many elements are in-between. Using b:button our form above would look like (See form1b.html):
<form name="main" action="action1.yaws" method="post">
<table>
<tr>
<td>Name</td>
<td><input name="name" type="text" size="40"/></td>
</tr>
<tr>
<td>Data</td>
<td><textarea name="data"/></td>
</tr>
</table>
<b:button b:action="submit" b:target="ancestor::form[1]">Send</b:button>
</form>

The b:action and b:target tags can also be used with the standard 'input' and 'button' elements. Which you use depends on whether you want normal HTML submission or backbase enhanced submission. You should never put all three tags in:
<input type="submit" b:action="submit" b:target="../../form" value="Send"/>

This would result in the form being submitted twice. Once via the normal HTML mechanism and the second time by backbase. You should also never just include the b:action attribute:
<input type="submit" b:action="submit" value="Send"/>

Note the absence of b:target. This would result in the standard HTML form submission being used. If you use any of the special backbase form facilities like b:destination (see later) on the form they'll be ignored.

None of this really shows the power of backbase forms though. You can very easily do the form submission via an Ajax request - and have the result returned by the form injected into the current pages HTML rather than doing a full page refresh. This is done by adding the b:destination and b:mode tags to the FORM element (See form2.html):
<xmp b:backbase="true">
<form name="main"
b:destination="id('replaceme')"
b:mode="replace"
action="action2.yaws"
method="post">
<table>
<tr>
<td>Name</td>
<td><input name="name" type="text" size="40"/></td>
</tr>
<tr>
<td>Data</td>
<td><textarea name="data"/></td>
</tr>
</table>
<b:button b:action="submit" b:target="ancestor::form[1]">Send</b:button>
</form>
<div id="replaceme">
<p>This paragraph will be replaced with the results of
the form submission.</p>
</div>
</xmp>

The b:destination tag is an XPath expression that identifies where the results of the form request will go. The submission will use Ajax to access the normal form action URL, but the data returned from that URL will be placed at the location of the destination. The b:mode indicates whether the data from the request will replace (as in this example) that node completely, or some other behavior ('replacechildren' for example will only replace the children of the destination node).

So entering the form data and pressing 'send' now will result in no page refresh and the result appearing in place of the div with the 'replaceme' id. The result returned from the form submit should be XHTML and can contain BXML. For example, it might look something like:
<?xml version="1.0" ?>
<div id="replaceme"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:b="http://www.backbase.com/b"
xmlns:s="http://www.backbase.com/s">
<p>Some paragraph</p>
</div>

Notice the div has some backbase namespaces. This is to allow BXML to be placed in the div, although the example doesn't use it here. Example form2a.html does demonstrate some BXML. It is functionally similar to the previous example but instead of inserting a paragraph into the div, it inserts an 's:execute' element to execute a task to display an alert. The effect is to display an alert box sent by the server as soon as the button is pressed:
<xmp b:backbase="true">
<form name="main"
b:destination="id('replaceme')"
b:mode="replace"
action="action2.yaws"
method="post">
<table>
<tr>
<td>Name</td>
<td><input name="name" type="text" size="40"/></td>
</tr>
<tr>
<td>Data</td>
<td><input name="data" type="text" size="40"/></td>
</tr>
</table>
<b:button b:action="submit" b:target="ancestor::form[1]">Send</b:button>
</form>
<s:execute id="replaceme"/>
</xmp>

In this case the data returned by the server as a result of the form request is something like:
<?xml version="1.0" ?>
<s:execute id="replaceme"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:b="http://www.backbase.com/b"
xmlns:s="http://www.backbase.com/s">
<task b:action="alert" b:value="Text of the alert"/>
</s:execute>

There is much more that can be done with form submission. When the submit event is sent as a result of the button press you can intercept it, check the validity of fields, and choose not to submit it, or allow it to continue. Multi-page wizard style forms are available, etc. I'll save those for another post.

Categories: ,

0 Comments:

Post a Comment

<< Home