Mittwoch, Dezember 12, 2007

Using OpenAjax events for building data-centric and forms based AJAX applications

Most of the business web applications on the Internet are HTML forms based applications where html elements are bound to data is the core functionality. I am talking about registration forms, dialogs and pages to display and modify records of a server side relational database system like in ERP or CRM systems.

Usually there is not a lot of drag & drop activity or popping visual effects here but the most active elements deal with data that comes from databases or other data sources. We need to display, edit and control records from a company's database and implement transactions on these entities.

Here is an approach to use the OpenAjax event mechanism to implement this kind of web applications. The beauty of it and the reason why I implemented this for the AjaxEngine open source project is that using events and namespaces is a far more open approach then the mechanism that I introduced some time ago and has a neat extensibility model.

Typical data-centric web pages

Using OpenAjax events for building data-centric and forms based AJAX applications

From a high level viewpoint onto pages that implement data-centric applications you see that the elements on the page can be categorized into the following cases:

  • Fields and other elements where values are shown and edited by the users (Input fields, checkboxes, ...)
  • Buttons that help editing these values (calendar popup, drop-down lists, ...)
  • Foreign key Lookup mechanisms (checking against a list of countries, ...)
  • Buttons that offer a way of navigation through huge data sources (|< first, next >>, ...)
  • Buttons that commit a current state to the backend system ([Update])
  • Buttons that trigger special transactions or back-end calculations

Forms in this kind of scenario are just a collection of html elements that together can be used to display or edit a single record of a given schema.

Where to use OpenAjax events

Events can help in these situations where a direct connection between components is not desired or otherwise problematic:

1. events on the field-level

On the field-level (inside the form) data is passed around when the value of a field or another data control is changed. This happens either by a user interaction with a field or another data control or as part of a situation on the record level for example when a new record is displayed.

If a field exists it can subscribe to the appropriate event and can display the value passed around. On the other side it can also publish a new event if the user changes the value.

It doesn’t matter if a real field is used or a slider, a calendar popup or a 3d spin control. Even multiple controls that subscribe to the same event can coexist side by side without knowing from each other.

Conclusion 1: Using OpenAjax events gives us the advantage of having a simple plugin mechanism that is extendable.

2. events from the menubar

Clicking a button already publishes the HTML built-in onclick event. However this event is only passed to those elements that are clicked directly or are part of the control hierarchy of the html object model. The menubar catches these events and transfers them into OpenAjax events that are passed to all elements that are interested because they have subscribed them. These events in contrary to the html DOM events are carrying a semantic by using the full eventname and eventually by carrying some data with them.

Conclusion 2: Using OpenAjax events can add semantic statements to events.

Conclusion 3: OpenAjax events are independent from the html DOM layout and therefore can help separating the UI model from the event model.

These 2 scenarios fit well into the OpenAjax event standard.

Antipatterns to OpenAjax events

1. events between tight coupled components

The datasource controller and the form element are 2 components that share some information flow. However every situation in this scenario is started by the datasource controller. The case where a user wants to “update” the datasource controller has to request the current form data from the form. Using is not practical because the form element that would receive the event will not be able to “attach” the current form data. A direct connection is more adequate approach by sharing a common interface like the 3 methods.

Conclusion 4: Using OpenAjax events to retrieve information is not a practical solution. Tight coupled components are still an option.

Note: Maybe some other control is interested in the fact that new data is available in the form which is done through a write() call. This can be the reason for publishing an event by the datasource controller that expresses that.

2. events between passed between client and server

The datasource controller also has to exchange data with the server. This is a direct end to end communication that happens every time a record is fetched from the server or a record should be updated. OpenAjax events can’t cross this boundary (yet) and again there is return data that is not available immediately when using asynchronous calls (I hope you do for reasons of robustness).

Conclusion 5: Remote Procedure Calls situations should be implemented by using a high level AJAX protocol.

Using attributes on controls to define the event names

One design convention that is used within the DataControls is that the eventnames that are used by controls can be split into 2 parts: the namespace and the local name.

The event “de.mathertel.datasource.search” that is used by the search button in the menubar has the namespace “de.mathertel.datasource” and the local name “search”. The eventname can be specified on the button itself ion 2 ways.

  1. When the eventname attribute contains a dot character it is assumed that the value already contains a full qualified event name.
  2. When the eventname attribute contains no dot character the parent elements are scanned for a “eventnamespace” attribute ant the effective event name is built by combining them.

Here is the sample of the html code:

<div id="datamenubar" class="VEMenuBar" eventnamespace="de.mathertel.datasource">
  <span hover="true" class="VEMenu" tabindex="1" eventname="search">Search</span>
  ...
</div>

This convention helps writing short html attributes and allows an easy changing of the namespace that is used for a collection of controls.

Currently the menubar control and the ajax form control both use this mechanism for building the full qualified even names from the eventname / eventnamespace attributes.

That’s the blue print of the current changes that took place in the AjaxEngine project. The even simplified the way Ajax Forms can be implemented and helps minimizing the code that we usually need to connect all the elements in a typical data-centric web application.

Have a look at the sample: http://www.mathertel.de/AJAXEngine/S06_AJAXForms/SimpleReader.aspx. If you scroll down the page you can also see a region with a protocol of the raised events.