When Binding won’t work with your ArrayCollection
I have no idea how much of my Flex career has been spent debugging why Bindings aren’t firing ‘correctly’ in a project, but I know I’ve banged my head against this specific problem a few times now.
A lot of the time I declare an ArrayCollection and whatever sort or filterFunction I need on it, and from that point forward I don’t want to reassign that reference to a new ArrayCollection or one returned from a service call because I don’t want to reapply the sort or FilterFunction.
myAC = new ArrayCollection();
var acSort:Sort = new Sort();
acSort.fields = [new SortField("name", true)];
myAc.sort = attSort;
If I detect a change on a data model or get some new data in a callback, I’ll swap out or modify the underlying Array in the ’source’ property of the ArrayCollection, and then call refresh() when I’m finished so any components bound to the ArrayCollection will be notified of the update
private function update(newData:ArrayCollection):void
{
myAC.source = newData.source;
myAC.refresh();
}
private function getText(ac:ArrayCollection):String
{
return ac.length.toString() + ‘ item(s)’;
}
<mx:Text id=”myText” text=”{getText(myAC)}” />
Great right? Sort and filterFunction are maintained, and components should update due to the refresh. Well, not exactly. If myAC is the dataProvider for a data driven component such as a List or DataGrid we’re in good shape, because when setting the dataProvider these components register for the COLLECTION_CHANGE event, which the refresh() will trigger. However, simple data-binding will NOT fire when this event is dispatched due to a refresh. There are many ways to work around this, one of which is to listen for the COLLECTION_CHANGE event on myAC when creating it and update component text, update variables, whatever you need to do in the listener. You could also keep a Bindable Boolean variable around and toggle it whenever data is updated, and then use that as a parameter to any functions that need to be called to update your components.
[Bindable] private var _dataUpdated:Boolean;
private function update(newData:ArrayCollection):void
{
myAC.source = newData.source;
myAC.refresh();
_dataUpdated = !_dataUpdated;
}
private function getText(updateFlag:Boolean):String
{
return myAC.length.toString() + ‘ item(s)’;
}
<mx:Text id=”myText” text=”{getText(_dataUpdated)}”/ >
In the example above the function ‘getText’ will be called whenever the _dataUpdated Boolean is toggled. This example is overly simplified because I could have just bound my text directly to the myAC.length property, which WILL work, but I wanted to illustrate that binding to the myAC reference will only fire if that reference is changed to a new ArrayCollection, NOT if refresh() is called.
There are probably at least a dozen other ways to work around this particular Binding issue, but there’s a quick one if you need it!
July 23rd, 2008 at 2:44 pm
I wonder why you would have e problem reassigning the sort. You may do
private function update(newData:ArrayCollection):void
{
newData.sort = myAC.sort;
myAC = newData;
}
thus relieving you from headaches due to sever head banging
It is just simpler…
July 23rd, 2008 at 2:56 pm
Oh I definitely agree that sometimes it’s simple to reassign a sort/filterFunction like that. The point of the post was more about how refreshing an AC won’t fire bindings on that AC reference, most of the time an update data funciton is much more complex than that, and a lot of times you don’t want to just reassign your AC reference. For one if you did have listeners registered for COLLECTION_CHANGE, now you have to add those listeners to the new AC because they’d be listening on the old AC. Maybe you don’t want the AC passed in to be mutable, most of the time my components keep their own collection around because the caller may not have expected you to add a sort/filter function because they could still be operating on the AC they handed off. All kinds of cases for working through an array, re-assigning the source of an AC, and then calling refresh, just simplified for a blog post
August 28th, 2008 at 12:45 pm
[...] - bookmarked by 4 members originally found by panahro on 2008-08-11 When Binding won’t work with your ArrayCollection http://www.thegoldhold.com/?p=13 - bookmarked by 2 members originally found by nacrofago on [...]