Creating a two-way binding between Model and Form in Flex
A quick sorry to all my Flex readership for the lack of Flex related posts these last few months. I though I would drop a quick tip / class I often use to create a two way binding between a form to a corresponding class model.
Flex provides a one way binding through its <mx:Binding> tags, if you are unfamiliar with this tag check out the section on them in Adobe’s Flex quick start guide. However if you want changes made to the model reflected in the form as well as changes made to the form reflected back in the model you need to set up two way bindings. To simplify this I have created a helper class (listed below) which then allows me to establish a two way binding.
package com.vibrant.components.Forms
{
import flash.display.DisplayObject;
import mx.binding.utils.BindingUtils;
import mx.binding.utils.ChangeWatcher;
public class ModelBinding
{
private var _modelWatcher : ChangeWatcher;
private var _componentWatcher : ChangeWatcher;
private var bindingsAreEstablished : Boolean = false;
public function ModelBinding()
{
}
/**
* Property field
* @default null
*/
private var _model : Object;
public function set model( value : Object ):void
{
_model = value;
updateBinding();
}
public function get model() : Object
{
return _model;
}
/**
* Property field, field within model to bind
* @default ""
*/
private var _field:String;
public function set field( value : String ):void
{
_field = value;
updateBinding();
}
public function get field() : String
{
return _field;
}
/**
* Property: target, component to tartget binding from model to.
*/
private var _target : Object;
public function set target( value : Object ):void
{
_target = value;
updateBinding();
}
public function get target() : Object
{
return _target;
}
/**
* Property: property, to bind to on target component
*/
private var _property : String = "text";
public function set property( value : String ):void
{
_property = value;
updateBinding();
}
public function get property() : String
{
return _property;
}
/**
* @private
* Updates bindings between component and model
*
*/
private function updateBinding() : void
{
if ( bindingsAreEstablished ) clearBindings();
if ( model != null && model.hasOwnProperty( field )
&& target != null && target.hasOwnProperty( property ) )
{
_modelWatcher = BindingUtils.bindProperty( target, property, model, field );
_componentWatcher = BindingUtils.bindProperty( model, field, target, property );
bindingsAreEstablished = true;
}
}
/**
* Clears bindings
*
*/
private function clearBindings() : void {
if ( _modelWatcher != null )
{
_modelWatcher.unwatch();
_modelWatcher = null;
}
if ( _componentWatcher != null )
{
_componentWatcher.unwatch();
_componentWatcher = null;
}
bindingsAreEstablished = false;
}
}
}
This class basically takes a model class, that has the data you would like to setup the bindings with in. The field name, the name of the property within the model class to bind to. A target, the form component to establish the view side binding with and finally you can specify an optional property that the binding should be made to on the form element. If unspecified, the ‘property’ defaults to “text” as this is the most often used property to bind to. So for example given the following User model:
public class UserModel
{
public var firstName : String;
public var lastName : String;
public function UserModel()
{
}
}
We could set up a binding to a TextInput as follows:
...
<mx:Script>
<![CDATA[
public var userModel : UserModel;
]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="First Name">
<mx:TextInput id="txtFirstName"/>
</mx:FormItem>
</mx:Form>
<modelBinding model="{userModel}" field="firstName" target="{txtFirstName}"/>
...
As you can see with this class you can quickly setup two-way bindings with your models.
Got an idea for a project?
Need a website? Web-enabled software to streamline your business? Just some advice?