Proof of Concept: Bindings in JavaScript

In another attempt to copy ideas from Actionscript 3 to JavaScript, I spent a few hours trying to implement bindings. I may try to implement an MVC framework like Cairngorm in JavaScript someday, and bindings play an important role in Flex and Actionscript.

Bindings keep UI elements in sync with data with minimal code. In Cairngorm, all application data lives in a ModelLocator singleton, so UI elements have a single point of reference for application data.

I’m sure there are many ways to implement binding in JavaScript, but I started with my ideal API:

Binding.bind(object, “property”, object2, “property2″);
  1. That method call does a few simple things:
  2. <ol>
  3.  <li>Adds generic getter and setter methods. The setter has a hook into the binding utility.</li>
  4.  <li>If an object is an applicable HTML element, it adds the appropriate event listeners that hook into the binding utility.</li>
  5.  <li>It stores the respective object/property pairs for each object.</|>li>
  6. </ol>
  7. This implementation forces you to use <code>object.set("propertyName", value)</code> in order to trigger binding. The binding trigger can easily be implemented in custom objects as well with this method call:
  8. <pre>Binding.trigger(object, "propertyName");

Where object is the bound object. This creates a cascade of calls setting the appropriate values on properties of other bound objects.

I avoided recursion by creating a unique transaction id every time Binding.trigger is called. The set method passes this id along internally so no object is changed twice in the same transaction.

So far I only support text and checkbox inputs, textareas, and select dropdowns. The selected option in a select dropdown doesn’t amount to a single property, but instead to element.options[element.selectedIndex].value. It was easy to override the get and set methods to allow Binding.trigger(element, "value").

See the example and check out the code. I used the Flow JavaScript library to normalize the DOM API (really just for addEventListener), but it doesn’t rely on any particular library.

« Developing Silverlight 1.0 RIAs: JavaScript Optimization Sass and Sprockets for Rails 3.1 »

5 Responses to “Proof of Concept: Bindings in JavaScript”

  1. Very nice. I’m assuming you’ve seen coherentjs (formerly of http://coherentjs.org/ now nabbed and hosted here http://github.com/trek/coherentjs/tree/master) and sproutcore (http://github.com/sproutit/sproutcore/tree/master) both have KVO/Binding stuff inspired by Apple’s Cocoa framework.

    Both have been snatched up by apple (and coherent has been removed from the net, basically).

    Bindings are definitely part of the javascript/RIA problem.

    TrekAugust 31st, 2008 at 3:19 pm

  2. This is exacly what I came looking for. Why did you choose to use the Flow framework, do you recommend it over other frameworks? Also, are you aware of any other approaches to the same goal of actionscript like binding? Thank you for this.

    JesseNovember 25th, 2008 at 12:12 pm

  3. @Jesse:

    I chose Flow because all it tries to do is normalize common DOM functions like addEventListener across browsers. Unlike most popular frameworks, it doesn’t introduce a new non-standard syntax like $().bind(). I would recommend it in many uses, but be aware that development on it is slow since it’s just one guy (a coworker of mine, Richard Herrera, who is a JavaScript genius).

    This pattern is very framework-agnostic though. I think the only thing you’ll need to change are the event listeners.

    And yes, I was heavily inspired by the patterns in Actionscript 3 that support Flex bindings.

    adminNovember 25th, 2008 at 12:23 pm

  4. Thank you. Which Flow package are you using? I would like to view the same uncompressed source.

    JesseDecember 3rd, 2008 at 8:53 am

  5. I probably just used the Flow core plus the extend module. Didn’t really need anything more for this exercise.

    adminDecember 3rd, 2008 at 9:17 am