The other day, on my FLEX On jQuery blog entry, Johan brought up data binding in the comments. Several other people have also mentioned data binding in the context of jQuery. Data binding, as a concept, is something that I am only vaguely familiar with; as such, I wanted to start playing around with some data binding ideas. The first thing I did was look at the FLEX documentation to see how data binding works.
Data binding is based on a class of components known as data providers. Data providers wrap around common data collections and expose event hooks in addition to standardized access and mutation methods. Because core data collection objects (such as the Array) don't announce mutation events, the data providers proxy the mutation methods, altering the internal data representation and triggering "collectionChange" events. UI components then subscribe to these "collectionChange" events and update their visual rendering as the underlying data collection is altered.
From what I have read, all data providers implement three interfaces:
Since I don't have the understanding at this time to explore all of these interfaces, I poked around a bit and picked out what I thought would be the most useful methods for this experiment. From the IList interface, I selected the following access and mutation methods:
- addItem( item )
- addItemAt( item, index )
- getItemAt( index )
- getItemIndex( item )
- removeItemAt( index )
- setItemAt( item, index )
Then, I looked at the ICollectionView interface and got the idea of the "collectionChange" event. This event will be triggered whenever the data provider's internal data collection is altered. The collectionChange event can have several different "kind" values depending on the way in which the data collection was altered (ADD, REMOVE, MOVE, RESET, etc.). After reading the documentation, I don't fully understand how the various kind values are implemented, so I just did some rough guesstimations.
As you can see above, I am binding to the submit event on the form. When the user submits the form, I am checking to see if the item value is in the current ArrayCollection instance. If it is, I remove it from the ArrayCollection; if it is not, I add the item value to the ArrayCollection.
I am also binding to the "collectionChange" event on the ArrayCollection. When the "collectionChange" event is triggered, I am using the "kind" property to figure out how to respond to the change - adding or removing Options. In a FLEX application, this change response would be encapsulated in a UI component class (ex. DataGrid); but, since we don't have a real UI component class in this demo, the change response is just being handled in a plain old event binding.
As you can see, almost every class method of the data provider, ArrayCollection, simply proxies methods on the core data array. These proxies provide two key features:
Uniform access and mutation methods. I happen to be using an array in this demo, but I suppose the underlying data item could be any type of object.
Mutation events. When the underlying data collection is altered, the data provider triggers events to alert all data consumers to the change.
At it's core, data binding seems to be nothing more than an event subscription and propagation architecture. I would assume that the aspect of data binding that people really want is the automatically updated visual rendering. Ironically, I don't think this part really has all that much to do with the actual data binding. It is up to the individual UI components to implement the UI changes. If you were to build a totally new UI component, data binding wouldn't magically do anything for you - you'd still have to wire the event response and alter the UI yourself.
Want to use code from this post? Check out the license.