Flex 4 bidirectional data binding: chicken or egg?

One of the many new features in Flex 4 is bidirectional data binding. I think it’s a useful addition because many times you have a data model that you bind to a form, and you want any changes in the form to be reflected back into the data model. With bidirectional data binding you can do this on the same line that you defined the binding, so there is no need of additional code (as was the case in Flex 3).

Here are the two syntaxes for declaring the binding as bidirectional:

  • <s:TextInput id=”txt” text=”@{value}”/> – notice the addition of “@”, this is the operator used to mark the binding as bidirectional
  • <fx:Binding destination=”txt.text” source=”value” twoWay=”true”/> – notice the twoWay attribute

However, I have to warn you that it might not work as you’d expect. Let’s have a look at the following code:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
   3:     xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" creationComplete="init()">
   4:     <fx:Script>
   5:         <![CDATA[
   6:
   7:             [Bindable]
   8:             private var labelValue:String = "Hello World!";
   9:
  10:             private function init():void {
  11:                 trace(labelValue);
  12:                 trace(txt.text);
  13:             }
  14:
  15:         ]]>
  16:     </fx:Script>
  17:     <s:TextInput id="txt" text="@{labelValue}"/>
  18: </s:Application>

We have a String variable with the default value “Hello World!”, and this variable is the source of data binding for the TextInput text variable. You might think that the execution of init() function will output:

   1: Hello World!
   2: Hello World!

Actually, the output is nothing! When I run this code for the first time I was puzzled. I then used the debugger to see what it was happening behind the curtains.

This is what I found:

  1. The application starts to initialize
  2. First the labelValue variable is initialized and triggers the property watcher (because it is used in binding)
  3. But at this point, the TextInput field is null, and the binding cannot be completed
  4. Next, the initialization of TextInput starts
  5. By default, the text property of this field is an empty string “”
  6. Because the TextInput is part of data binding too (remember the data binding is bidirectional in my code), the property watcher executes and sets the value of labelValue to empty string
  7. Finally, the application finishes its creation and the init() function is executed. By now, both the variable and the text property of the TextInput have the same value, empty string

Elementary my dear Watson!

If I want the code to work as I intended, I have to initialize the labelValue variable on the creationComplete event or after:

   1: private function init():void {
   2:     labelValue = "Hello Wold!";
   3: }

I guess this is one of those problems: who was first, the chicken or the egg?

Adobe AIR 1.5.2 is out

Adobe AIR 1.5.2 is out! You can download it from here, and here you can read the release notes. This update improves reliability, compatibility, and security. More than 50 bugs were fixed, many of them Linux related (for the complete list, check the release notes).