Binding Flex TextInput UI Controls to a DataProvider

In Flex when you bind data to a UI control like a DataGrid, the grid cells refresh every time the dataSource changes. The reverse is also true if the DataGrid is enabled for editing. That is, the dataSource is also updated when you edit a cell.

The TextInput can be bound as well so that when the dataSource changes, the value of the TextInput will automatically update. However, unlike the DataGrid, changing the text of the TextInput will not automatically update the dataSource. Take the following code for example (assuming “source” is a String variable):

<mx:TextInput id="text1" text="{source}" change="{source= text1.text}" />

When the TextInput is changed, the value of source remains the same. It’s only bound one-way. If you want the value of source to be updated when TextInput changes, it’s actually easy, but there are at least five (5) different ways to do it of which I know. For the most straight-forward two-way binding, you could update the TextInput code like so:

Technically source is not bound to the TextInput, but it does produce the desired result. source is updated manually whenever the valueCommit event fires. The valueCommit event fires when the TextInput text has been changed onBlur (ie when when TextInput loses focus). If you prefer source to be updated on every key stroke, you can change valueCommit to change instead and the update will occur on every keyUp. If I’m updating a database or making a service call, I prefer valueCommit so the back-end code only fires once after the user is finished updating the field. If the TextInput is an ajax-style auto complete or lookup, the change event might be more desirable so the application can react after each key stroke.

As I mentioned there are five methods to do this. You can bind controls using Flex’s binding features in either MX code or ActionScript. Depending on your application one may be better than the rest as far as keeping your code clean and consistent. For the most part they all achieve the same result. Below is source code that demonstrates all five techniques:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="{init()}">
	<mx:Script>
		<![CDATA[
			import mx.binding.utils.BindingUtils;
			import mx.binding.utils.ChangeWatcher;
 
			/**
			 * Called at creation complete and initializes all of the examples
			 */
			private function init():void
			{
				this.initExample2();
				this.initExample3();
				this.initExample4();
				this.initExample5();
			}
 
			/**
			 * Example 1: simple inline binding (see the MXML)
			 * -----------------------------------------------------------------------
			 */
 
			[Bindable]
			private var value1:String = "example 1";
 
			/**
			 * Example 2: use ChangeWatcher to assign a change watcher to text2.text
			 * -----------------------------------------------------------------------
			 */
 
			[Bindable]
			public var value2:String = "example 2";
 
			private var watcher2:ChangeWatcher;
 
			public function initExample2():void
			{
				watcher2 = ChangeWatcher.watch(text2,"text",text2changed);
			}
 
			/**
			 * notice that the argument is an event
			 */
			public function text2changed(event:Event):void
			{
				this.value2 = (event.currentTarget as TextInput).text;
			}
 
			/**
			 * Example 3: use BindingUtils to bind a change watcher to the text3.text setter
			 * -----------------------------------------------------------------------
			 */
 
			[Bindable]
			private var value3:String = "example 3";
 
			private var watcher3:ChangeWatcher;
 
			public function initExample3():void
			{
				watcher3 = BindingUtils.bindSetter(text3changed,text3,"text");
			}
 
			/**
			 * notice that the function argument is a string (the value of text3.text)
			 */
			public function text3changed(val:String):void
			{
				this.value3 = val;
			}
 
			/**
			 * Example 4: Use BindingUtils to bind text4.text to this.value4 (notice value4 has to be public)
			 * -----------------------------------------------------------------------
			 */
 
			[Bindable]
			public var value4:String = "example 4";
 
			private var watcher4:ChangeWatcher;
 
			public function initExample4():void
			{
				watcher4 = BindingUtils.bindProperty(this, "value4", text4, "text");
			}
 
			/**
			 * Example 5: using MX:Binding in the MXML (see below)
			 * -----------------------------------------------------------------------
			 */
 
			[Bindable]
			private var value5:String = "example 5";
 
			public function initExample5():void
			{
				text5.text = this.value5;
			}
 
		]]>
	</mx:Script>
 
	<mx:HBox>
		<mx:TextInput id="text1" text="{this.value1}" change="{this.value1 = text1.text}" />
		<mx:Label id="label1" text="{this.value1}" />
	</mx:HBox>
 
	<mx:HBox>
		<mx:TextInput id="text2" text="{this.value2}" />
		<mx:Label id="label2" text="{this.value2}" />
	</mx:HBox>
 
	<mx:HBox>
		<mx:TextInput id="text3" text="{this.value3}" />
		<mx:Label id="label3" text="{this.value3}" />
	</mx:HBox>
 
	<mx:HBox>
		<mx:TextInput id="text4" text="{this.value4}" />
		<mx:Label id="label4" text="{this.value4}" />
	</mx:HBox>
 
	<mx:HBox>
		<mx:TextInput id="text5" />
		<mx:Label id="label5" text="{this.value5}" />
	</mx:HBox>
 
	<!-- Configure the binding here in MXML -->
	<mx:Binding source="text5.text" destination="this.value5" />
 
</mx:WindowedApplication>

If you know of any other ways to bind data to UI Controls, please post a comment.

14 Responses to “Binding Flex TextInput UI Controls to a DataProvider”

  1. ketan July 6, 2009 at 6:51 am #

    Thanks…! This is something good to know and very helpful.

  2. mo south July 27, 2009 at 1:01 pm #

    Dude, this saved me from going bald.
    thank you.

  3. Rossie September 16, 2009 at 10:43 am #

    It helped me also a lot, thank you!

  4. Pieero January 5, 2010 at 9:55 am #

    I’d prefer use the syntax without id, it is more generic to me

    <mx:TextInput text=”{source}” valueCommit=”{source = text;}” />

  5. Jason January 5, 2010 at 1:27 pm #

    Thanks Pieero. My habit is to include the object reference to make it clear where the value is coming from. However, your suggesting is interesting to me because I wonder due to the Flex scope chain, that the value of “example.text” might be located faster by simply using “text”. I believe it might be within scope of the TextInput class, whereas my version has to look outside to the parent component scope, then back into the TextInput. I’ll have to test that out and see.

  6. Pieero January 6, 2010 at 5:48 am #

    @Jason
    Unfortunately, I was a little too presumptuous.
    This is not working, and I saw it only after posting, sorry.

    I would expect to find a way to set context in inline code.
    But even using the event.target.text, it says “event does not exists”, while we can write function_handler(event).

    What a pity.

  7. Jason January 6, 2010 at 12:31 pm #

    @Pieero
    Ah, interesting. I’ve found binding to be surprising sometimes as well. The reason I suspect is because string binding code is not directly executed. Instead it is actually parsed by substituting a lot of “magic” variables and then interpreted inside the binding classes.

    So some variables don’t work correctly due to the fact that the binding code doesn’t recognize them. however you don’t notice what is happening until you stumble onto some of these variables.

    thanks for the comment, though, it’s an interesting thing to know.

  8. Max February 24, 2010 at 11:45 am #

    I want to have a textinput that converts the users entry to a currencyFormat at the point of entry. As the user enters the values, the currencyformatter kicks in and formats as he types. Dunno if anyone has done anything like that. I’d like any ideas. Thanks and nice work

  9. Ansury August 19, 2010 at 9:17 pm #

    Download link is broken :(

    • Jason August 24, 2010 at 9:49 pm #

      hmm it appears that when i migrated servers the zip files got lost. crap. i’ll try to see if i can find it. sorry…

      • Bruno Lemos January 15, 2011 at 6:22 pm #

        Still broken :(
        please someone post the code or send me

        • Jason January 27, 2011 at 12:47 am #

          I just found the old code and pasted it inline on the page.

  10. Michael Mattan November 7, 2011 at 8:41 am #

    If you use the following at-notation, the values will be synchronized in both ways:

    • Jason November 7, 2011 at 3:45 pm #

      The original article was written for Flex 3 before the @ notation was available, but I would definitely use @ notation with Flex 4.

Leave a Reply

Please leave these two fields as-is: