Conditional visualization in Cairngorm 2.x using the ChangeWatcher class
Data Binding is one of the most important and powerful flex features and the Cairngorm framework makes a full use of it in its Model View Controller design pattern.
In a standard and simple use of Cairngorm we have a view with some controls with dataProviders directly bound to the ModelLocator, if you don't have a clear view of how these things work you'll have a better outlook viewing the diagram on cairngormdocs.org
Sometimes we want to have in a view only some data that satisfies certain conditions, we have to filter the collection before passing it to the view. Flex gives the possibility to use a filter function associated to the collection; if you are considering a small application this is a viable solution but in an Enterprise RIA application probably we cannot apply a filter function, because that data source can be a data provider for different views that need the complete collection.
The flex ChangeWatcher class provides a complete different solution. From the flex 2 api: “
The ChangeWatcher class defines utility methods that you can use with bindable Flex properties. These methods let you define an event handler that is executed whenever a bindable property is updated.â€
Let'see a tipical view in Cairngorm:
<MyView ... >
<mx:DataGrid dataProvider=â€{MyModelLocator.getInstance().myDataSource}â€
itemRenderer=â€MyItemRenderer†/>
</MyView>
We have no way to intercept changes in the data source because the data binding will make changes effective in the view instantaneously.
Using the ChangeWatcher and the view helper we interpose a layer that prepares the data before sending them to the view.
The new View:
<MyView ... >
<MyViewHelper id="myViewHelper" />
<mx:ArrayCollection id=â€myDataProvider†/>
<mx:DataGrid dataProvider=â€{myDataProvider}â€
itemRenderer=â€MyItemRenderer†/>
</MyView>
The ViewHelper:
package ...
{
...
public class MyViewHelper extends ViewHelper
{
private var myChangeWatcher:ChangeWatcher;
public function MyViewHelper() {
myChangeWatcher = ChangeWatcher.watch(MyModelLocator.getInstance(), “myDataSourceâ€, prepareDataProvider);
}
private function prepareDataProvider(event:Event) {
var myAC:ArrayCollection = new ArrayCollection();
for each(var item:Object in MyModelLocator.getInstance().myDataSource) {
//if item satisfies certain conditions
myAC.addItem(item);
}
view.myDataProvider = myAC;
}
Every time the data source is updated, the handler is called and the collection is filtered. It is convenient that the responder updates the entire collection at once and not adding items one by one, because the handler would be called every time. To stop watching the data source you can call the unwatch() function on the changeWancher instance in the ViewHelper.
This is only one of the possible solutions we can use thanks to the flexibility of data binding.