Friday, February 10, 2012

Binding (Part 3)


Question: How to define a data binding in action script?
Answer: We use bindSetter() method to set up a data binding.




<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx">

 <s:layout> <s:VerticalLayout/> </s:layout> 

<fx:Script> 

  <![CDATA[ 

    import mx.binding.utils.*; 

    import mx.events.FlexEvent; 

    // Method called when myTI.text changes. 

    public function updateMyString(val:String):void { 

      myTA.text = val.toUpperCase(); 

    } 

    <!-- Event listener to configure binding. --> 

    public function mySetterBinding(event:FlexEvent):void { 

      var watcherSetter:ChangeWatcher =      

        BindingUtils.bindSetter(updateMyString, myTI, "text"); 

    }

 ]]>

 </fx:Script> 

 <s:Label text="Bind Setter using setter method"/> 

 <s:TextInput id="myTI" text="Hello Setter" /> 

 <s:TextArea id="myTA" initialize="mySetterBinding(event);"/>

</s:Application>






Question: How to define a binding watcher.
Answer: Flex includes the mx.binding.utils.ChangeWatcher class that you can use to define a data-binding watcher. Typically, a data-binding watcher invokes an event listener when a binding occurs. To set up a data-binding watcher, you use the static watch() method of the ChangeWatcher class.







<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" initialize="initWatcher();"> <s:layout> <s:VerticalLayout/> </s:layout> 

<fx:Script> <![CDATA[

   import mx.binding.utils.*; 

   import mx.events.FlexEvent; 

   import mx.events.PropertyChangeEvent; 

   public var myWatcher:ChangeWatcher; 



  // Define binding watcher. 

  public function initWatcher():void {

     // Define a watcher for the text binding. 

     ChangeWatcher.watch(textarea, "text", watcherListener); 

  } 

  // Event listener when binding occurs. 

  public function watcherListener(event:Event):void { 

     myTA1.text="binding occurred"; 

     // Use myWatcher.unwatch() to remove the watcher. 

  } 

]]> </fx:Script> 

<!-- Define a binding expression to watch. --> 

<s:TextInput id="textinput" text="Hello"/> 

<s:TextArea id="textarea" text="{textinput.text}"/> 

<!-- Trigger a binding. --> 

<s:Button label="Submit" click="textinput.text='Goodbye';"/> 

<s:TextArea id="myTA1"/>

</s:Application>






Question: How to use Bindable Metadata tag?
Answer: This tag can be used at three places.
1.     Before a public class declaration.
[Bindable]
public class myTextArea extends TextArea()
In that case all public properties defined as variables, and all public properties defined by both getter and setter methods, of that class become usable. For every non-public property separate tag needs to be inserted. If the property value remains the same on a write, Flex does not dispatch the event or update the property, where not the same translates to the following test:
(oldValue !== value)
That means if a property contains a reference to an object, and that reference is modified to reference a different but equivalent object, the binding is triggered. If the property is not modified, but the object that it points to changes internally, the binding is not triggered.
2.     Before a public, protected or private variable to make that property support binding.
 [Bindable]
 public var foo:String;
Flex generates an event propertyChange, as told before. We can also specify event name but in that case we are responsible to dispatch the event.
3.     Before a public, protected or private property defined by getter and setter method.
[Bindable]
public function set shortNames(val:Boolean):void {
...
}
public function get shortNames():Boolean {
...
}
Here Flex generates propertyChange event for the property. To determine the property
change Flex calls getter() to get current value. We can specify the name of event, but then
we are responsible for dispatching the event or update the property.
[Bindable(event="changeShortNames")]
public function set shortNames(val:Boolean):void {
... // Create and dispatch event.
dispatchEvent(new Event("changeShortNames"));
}
// Get method.
public function get shortNames():Boolean {
...
}
Now Flex does not check to see if old and new values are different.

In an mxml file, we can make all the public properties that we define as variables, usable as source for binding, by simply including bindable tag in metadata tag.
   [Bindable]
Otherwise we can use bindable tag in block to make some properties bindable.

Question: Define Bindable working chain and how to use it.
 Answer: When a property is source for data binding, Flex keeps track of that property along with
the chain of properties leading up to it. This entire chain of properties including source property is
called bindable property chain.

Here user.name.firstName.text is bindable property chain that includes user, name, firstname and
text. For data binding mechanism to work on text, only text property needs to be bindable, but if
we want to assign new value to any part of chain, every element in chain must be bindable.
When using BindingUtils.bindProperty() or BindingUtils.bindSetter() method, we specify bindable property chain as an argument. For example the bindProperty() method has signature:
public static function bindProperty(site:Object, prop:String,
host:Object, chain:Object, commitOnly:Boolean = false):ChangeWatcher

The host and chain specify the source of data binding expression.

bindProperty(myText, 'text', user, ["name","firstName","text"]);
In the above example the ["name","firstName","text"] defines the bindable property chain relative to user object and user is not part of chain. In an MXML data-binding expression, the bindable property chain is always relative to this. Therefore, to define a data binding equivalent to the MXML data binding expression shown above, you write the bindProperty() method as the following example shows:
bindProperty(myText, 'text', this, ["user","name","firstName","text"]);

Question: What are the important considerations while using data binding?
Answer: There are few considerations.
•We cannot bind to style properties.
If we bind a model into the dataProvider property of a component, we should not change items in the model directly. Instead, change the items through the Collections API. Otherwise, the component to which the model is bound is not redrawn to show the changes to the model. For example, instead of using the following:
 myGrid.getItemAt(itemIndex).myField = 1;
We would use the following:
 myGrid.dataProvider.editField(itemIndex, "myField", 1);
Array elements cannot function as binding sources at run time. Arrays that are bound do not stay updated if individual fields of a source Array change. Binding copies values during instantiation after variables are declared in an tag, but before event listeners execute.

Question: What is TurboBinding tag and how to use it?
Answer:  You can read about it here.

No comments: