Oct 01 2008
Using ChangeWatcher
Data binding is one of the best things about Flex, frameworks like Cairngorm rely heavily on data binding. But what if you want to detect a change in variable value and then also do something else. Changewatcher comes in handy during times like those.
import mx.binding.utils.ChangeWatcher;
This is the class i am talking about, it lets you listen for changes in a variable. Lets say we have a class variable totalItems and we need to detect changes to that variable. This is a simple class.
class Model {
//i shall leave the constructor to you
[Bindable]
public var totalItems:Number;
}
}
Now to detect changes to this variable, the code would look something like,
public var watcherInstance:ChangeWatcher;
[Bindable]
public var model:Model;
public function init():void{
//this is useful if you want to unwatch or stop detecting changes to this variable
//ofcourse init function has to be called
model = new Model();
watcherInstance = ChangeWatcher.watch(model,["totalItems"],itemsChanged);
}
public function itemsChanged(event:PropertyChangeEvent):void{
//this function is called as soon as value of totalItem changes.
//if you want to stop watching this variable.
watcherInstance.unwatch();
}
So you can see that this is very easy way of detecting changes, the only thing to keep in mind is that the variables being watched have to be Bindable. You can also detect changes within chain of classes.
For Eg. ChangeWatcher.watch(model,[“shoppingCart”,”totalItems”],itemsChanged); the variable totalItems is inside the class ShoppingCart which is initialized in Model. So your chain of variables can be as long as you want.
Other Important thing to note is that the line code after the variable will be executed only after your listener function is called. Its not asynchronous like URLLoader etc.
EDIT: 02/20/09 Imp Note:
If you are tracking changes to a number, your changewatcher function will fire only if the number changes. Lets say your variable totalItems is 1 and after performing some calculation its again 1, in this situation your changewatcher won’t fire because the value of variable hasn’t changed. It can cause crazy bugs in your application and i have been bitten by this couple of times now.
The example below shows how you can watch a chain and also how every variable has to be bindable etc.
Click here for the source.
Hi,
The information provided was really helpful.
What if I want to check if an array collection got changed in the model?
Is it possible?
One of possible ways I know is
ChangeWatcher.watch(model,[“arraycollection”, “length”],itemsChanged);
The above works but its not necessary that lenght should always change it can the be the data which got changed. Is it possible to be detected using changeWatcher?
for all the collection classes there is collectionChange event broadcasted which you can use to detect changes within the collection object. you don’t have to use Changewatcher for it.
BTW: I found out the hard way that this watcher is only partially implimented in Flex 3.x. You can NOT watch booleans with this, it breaks, and doesnt do a thing.
changewatcher uses propertychangeevent, so it might not work with certain properties. if the property is not bindable and public/accessible by outside classes then changewatcher won’t be able to watch it as simple as that.
you can make a boolean watchable but it has to be a public property of the object and it has to be bindable, you can see for urself in the following example.
< ?xml version="1.0" encoding="utf-8"?>
< ![CDATA[ import mx.binding.utils.ChangeWatcher; import mx.events.FlexEvent; import mx.events.PropertyChangeEvent; [Bindable] public var checkBool:Boolean = false; private var watcher:ChangeWatcher; protected function application1_creationCompleteHandler(event:FlexEvent):void { // TODO Auto-generated method stub watcher = ChangeWatcher.watch(this,["checkBool"],selectedCheckbox); } public function selectedCheckbox(event:PropertyChangeEvent):void{ checkBox.selected = checkBool; } protected function button1_clickHandler(event:MouseEvent):void{ // TODO Auto-generated method stub if (inputText.text.length > 2){
checkBool = true;
} else {
checkBool = false;
}
trace(checkBool);
}
]]>
if you change the checkBool to private its not going to work. enjoy.
Thanks for the nice article, the code snippet is also very useful
Regards,
Omar Mostafa
Very nice example to get good understanding on ChangeWatcher. Thank u so much.
Also it is some what high end, with out the three controls, like textInput, checkbox, and Button. For new people it may be some what tough to follow. Any how thanks for your work.
Thanks for the info, a very good info…