Wiki Markup |
---|
{scrollbar} h1. Data Binding and Model-View-Controller Framework As the XUL framework progressed, Pentaho developed a need for a clean, underlying model-view-controller (MVC) architecture application. MVC provides for a clean separation between application data (models), view logic (controllers) and the user interface (views). This separation creates loosely coupled components that are easier to maintain and test. For a more in-depth look at building Pentaho XUL applications with the MVC pattern, please refer to the excellent MVC in XUL applications article by Aaron Phillips: [http://wiki.pentaho.com/display/PLATFORM/MVC+in+Pentaho+Xul+Applications] At the heart of any MVC application framework lies a method for synchronizing data between the models and views. Many frameworks leave this "housekeeping" to the developer. XUL bindings offer a more developer-friendly approach. h2. What's in a Binding? A XUL binding object consists of four primary and two optional pieces of data: * Two *XulEventSource* objects -- one "Source," the other "Target" -- and a property for each to "Bind" together. * A binding strategy (one-way, bi-directional, or bind-once). A converter object to manage data translation between the two is also an option. h2. Creating a Binding Object There are several methods for creating a binding object in the XUL framework. Some are as simple as calling *bind()* with four strings from an event handler. All of those methods are covered in the aforementioned MVC document. Below is the most basic representation of a binding: {code} Binding bind = new Binding(sourceObject, "firstName", targetObject, "value"); {code} When added to a binding context (explained later in this guide) it will synchronize data between *sourceObject* and *targetObject* by way of *firstName* and *value* respectively. Because Java lacks first-class support for properties, and it's bad form to write objects with direct member access, a binding accesses data by way of the JavaBean standard. At the JavaBean level, the binding looks something like this: {code} sourceObject.getFirstName() => targetObject.setValue() sourceObject.setFirstName() <= targetObject.getValue() {code} h2. Binding Strategies By default, a binding object represents a synchronization bi-directionally. Any change to the source will update the target and visa-versa. You can optionally prescribe for a one-way binding between source and target as such: {code} binding.setBindingType(Binding.Type.ONE_WAY); {code} Where *ONE_WAY* is a type defined in Binding.Type enumeration. A one-way binding will send data from the source to the target but not the other way around. Future versions will introduce the concept of a "bind-once" strategy that will in essence "flash" a snapshot of data between objects at the time of the binding's instantiation. h2. Conversions You can further extend the flexibility of your bindings by providing a *BindingConvertor* object to manage the translation of data between objects: {code title="*BindingConvertor.java"* {code} public abstract class BindingConvertor<V, R> { ... public abstract R sourceToTarget(V value); public abstract V targetToSource(R value); } {code} Below is a simple implementation that binds the value of a *XulTextbox* with the *selectedIndex* of a *XulMenuList*. When a user enters a numeric string into the text box, it will be converted into an integer before being passed to the *setSelectedIndex* method of the menu list: {code} Binding binding = new Binding(textbox, "value", dropdown, "selectedIndex"); BindingConvertor conversion = new BindingConvertor<String, Integer>(){ @Override public Integer sourceToTarget(String value) { return Integer.parseInt(value); } @Override public String targetToSource(Integer value) { return value.toString(); } } binding.setConversion(conversion); {code} h2. The Binding Context Bindings in and of themselves don't actually do anything; they simply describe the relationship between objects. The actual establishment of a binding is performed by a *BindingContext* object. However, you never have to deal with a *BindingContext* directly because every *XulDomContainer* has one. To add a new binding object to the context, simply pass the binding to the *addBinding()* method of the *XulDomContainer*. |
Page Comparison
General
Content
Integrations