JavaScript in betterFORM

June 16, 2010 at 11:51 am Leave a comment


Using JavaScript with XForms

Before diving into the details of how to use JavaScript with XForms (and specifically betterFORM) it’s worthwhile to think about why you might want to use it. Isn’t it one of the most often mentioned arguments that XForm makes writing JavaScript superfluous? The authors of the XForms spec. have been more cautious by stating:

“(…)reduces the need for scripting”

This clearly says that scripting might and most likely will be needed to build full applications. XForms is not the answer to all application needs. It is a domain-specific language especially designed for the purpose of form processing. It does this job extraordinary good and offers a rich set of features like strong typing, calculations and validations, dependency tracking, a powerful submission module, actions and event processing etc. etc. It has a MVC architecture and an abstract UI. The resulting forms are device-independent and can be run or ported to other XForms implementations as it’s an open standard.

So we know why we have decided for XForms but why should we want to use JavaScript?

When you write XForms you typically don’t need to worry about writing JavaScript for processing your forms. XForms gives you all functionality to do so in a declarative way. But you need more than ‘just’ forms when you want to build complete applications:

  • you will need some layout facility like CSS to render your forms nicely
  • you may want subforms that communicate with each other
  • you’ll likely want a nice AJAXified user interface that update only parts of the screen
  • you will want to have your forms modularized instead of monolithic
  • you may want to interact with the browser directly by hooking into browser-events or manipulating CSS classes
  • you may want to integrate a ‘foreign’ component and let it speak to the XForms processor

As a domain-specific language XForms needs to integrate with the host language to cover the last mile from abstract UI to a concrete rendering on a specific device. XForms defines an IDL interface which can be used by the host. It does not offer much yet besides getting a model, an instance and call the rebuild, recalculate, revalidate and refresh methods. It’s quite likely that this interface will be extended in future versions of XForms.

#include "dom.idl"

   pragma prefix "w3c.org"

   module xforms {
      interface XFormsModelElement : dom::Element {
         dom::Document getInstanceDocument(in dom::DOMString instanceID)
            raises(dom::DOMException);
         void rebuild();
         void recalculate();
         void revalidate();
         void refresh();
      };
   };

betterFORM supports this interface and has an implementing class. More on that later.

In the meantime the XForms implementers have developed their own (vendor-specific) approaches to deal with the situation and allow the execution of JavaScript from XForms and vice versa.

The following section gives an overview over the JavaScript API of betterFORM.

The betterFORM JavaScript API – from JavaScript to XForms

When you are running an XHTML/XForms document with betterFORM your browser will get a HTML/JavaScript representation of the original document. This will contain all required script imports for working with the API . No further special preparations are needed.

betterFORM uses the Dojo toolkit for its client-side JavaScript layer. Dojo also allows declarative programming to create JavaScript components. When you look at the source view of your browser when rendering an XForms with betterFORM you will notice the following lines (formatted here for readability):

<div dojotype="betterform.FluxProcessor" jsId="fluxProcessor" id="fluxProcessor" sessionkey="1276614396436" contextroot="/betterform">
<div class="xfModel" style="display:none" id="model1" jsId="model1" dojoType="betterform.XFormsModelElement"></div>
...

The first div creates an instance of FluxProcessor. FluxProcessor is a Proxy for the actual processor at server-side and when calling XForms from JavaScript you will normally use one of its functions. Notice the attribute ‘jsId’. This establishes a global JavaScript variable that allows easy access to the processor. To call one of the functions of FluxProcessor you simply prepend it to the function name e.g.:

fluxProcessor.dispatch("myId");

The second div is a placeholder for the model in your XForms and implements the IDL interface mentioned above. There will be one instance of XFormsModelElement for each model in the XForms document. Same here –  you can reference the JavaScript XFormsModelElement via its jsId which will be the id of the model in your document. If you want to refresh the model just call:

model1.refresh();

The FluxProcessor API

Here are the most important functions the FluxProcessor offers:

dispatchEvent(/*String*/ targetId)

dispatches a DOMActivate to a trigger thereby firing the actions attached to that trigger

Example:
fluxProcessor.dispatchEvent("myTrigger');

dispatchEventType(/*String*/ targetId, /*String*/ eventType, /*Object*/ contextInfo)

dispatches a Event of a specific type to given target id

Example
fluxProcessor.dispatchEventType(this.xfControl.id,"DOMFocusOut");

setControlValue(/*String*/ targetId, /*String*/ newValue)

sets the value of the control with given id to new value

Example:
fluxProcessor.setControlValue("myInput","hello world");

close()

initiate a shutdown of the processor. If dirty data exist and skipshutdown is not ‘false’ a confirmation dialog will be shown.

Example:
fluxProcessor.close();

setLocale(/*String*/ locale)

set the locale for the form. Must be a two-letter ISO 639 code. This will affect the rendering of numbers and dates.

Example:
fluxProcessor.setLocale("de");

showHelp()

shows help in a popup window if any is available for the currently focussed control.

Example:
fluxProcessor.showHelp();

There are some further goodies in API but i leave that for self-study for now. In the majority of cases you will only need setControlValue and dispatchEvent to interact which your forms. With dispatchEvent you can activate any trigger in your document and it can be an easy bridge between the browser world and the XForms processor. dispatchEventType on the other hand lets you dispatch any type of event to the XForms document and even pass some contextInfo if needed.

The XFormsModelElement API

There’s not much you can do with the XFormsModelElement at the moment that you can’t do through functions of FluxProcessor. With one important exception – if you for some reason want the instance data of your form at the client-side then you have to use getInstanceDocument() function.

In betterFORM you have to use the function like this:

model1.getInstanceDocument(/*String*/ modelId, myCallBack);
/*
    A function that receives the returned instance data
*/
function myCallBack(data){
    //if you have Firebug active you can list out the returned XML
    console.dirxml(data);
    ...
}

If you need or want your XML as a String use getInstanceAsString() instead (same arguments).

From XForms to JavaScript

Sometimes you may experience situations where the call to a simple JavaScript function makes life a lot easier.  Probably any XForms implementation out there has some way to do that. In betterFORM we simply use the syntax of HTML:

<xf:input id"input1">
    <xf:label>input1</xf:label>
    <xf:action ev:event="xforms-value-changed">
        <script type="text/javascript">
            dojo.byId("input1").attr("style","background:lightyellow;");
        </script>
    </xf:action>
</xf:input>

In this example the background of the rendered control will be colored in lightyellow when the control gets an ‘xforms-value-changed’ event.

JavaScript has become an important part of modern web applications. There are only few users still accepting a pure request/response oriented interface – the new user interfaces are just too attractive. XForms can hardly be beaten when it comes to complex forms but the same is true for JavaScript in the domain of attractive and dynamic user interfaces. Using JavaScript and XForms together gives you the powerful package you need to build cross-browser and state-of-the-art web applications.

Entry filed under: betterFORM, Dojo, Uncategorized, XForms. Tags: , , , .

Getting started with betterFORM XRX (lightSteelBlue) Using Subforms with betterFORM

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Trackback this post  |  Subscribe to the comments via RSS Feed


Recent Posts

betterFORM tweets


%d bloggers like this: