Filter an ArrayCollection and don’t lose the original data
Yesterday, one of my students asked me about recovering the original data of an ArrayCollection if this ArrayCollection has a filter applied.
In Adobe Flex, the ArrayCollection class has a property called filterFunction. We can assign a function reference directly to this property and then apply a refresh() to the ArrayCollection instance.
This is an example.
// Defining the ArrayCollection instance
private var ac:ArrayCollection = new ArrayCollection([
{label:"Adobe Flex", data:"Fx"},
{label:"Adobe Flash", data:"Fl"},
{label:"Adobe After Effects", data:"Ae"},
{label:"Adobe Flash Player", data:"fp"}]);
//Defining the filter function
private function flashFilter(obj:Object):Boolean
{
return obj.label.toLowerCase().indexOf("flash") != -1;
}
//Applying the filter
ac.filterFunction = flashFilter;
ac.refresh();
Once the filter is applied, the ArrayCollection hides all the objects that don’t pass the validation in the function and shows the objects that do.
An ArrayCollection stores internally an instance of the Array class. You can see that in the previous example where I place an array inside the constructor of the ArrayCollection.
An ArrayCollection acts as a “wrapper” for the array instance enabling functionality that belongs to collections and lists. This functionality can be, filtering, sorting, add/remove/modify data and more.
After you filter an ArrayCollection instance the “wrapper” only shows the unhidden objects and it seems like it only has 2 elements (in my example), I mean if you test the “length” property after the filter you will see that it shows the value 2. But we know the truth, the ArrayCollection actually has 4 elements. If you want to get back this 4 elements without clearing the filter you have to deep into the ArrayCollection and find the source. This source, as I said previously, is an Array.
You will find the source using, in fact, the “source” property of the ArrayCollection. The array that will give you this property is the complete set of data that the ArrayCollection is storing without any filter. Just don’t forget that “source” is giving you an instance of an Array and not an instance of an ArrayCollection.
//continuing the previous example...
//Applying the filter
ac.filterFunction = flashFilter;
ac.refresh();
//Test the length property of the ArrayCollection
trace(ac.length); // 2
//Test the source property of the ArrayCollection
trace(ac.source) // [object Object],[object Object],[object Object],[object Object]
//Test the length property of the source property
trace(ac.source.length) // 4



wow, very good Alberto ^^ this is a genial post
Nice article. I thought I’d add that if you have an ArrayCollection that you want to filter and/or sort without modifying the original ArrayCollection, you can use the ListCollectionView class and modify how you can view that ArrayCollection without modifying the original ArrayCollection or Array.
Also if you are working with ArrayCollections that contain other ArrayCollections (i.e. hierarchical data), you encounter an even trickier situation because you cannot just access the “source” property to get the original data.
But depending on how you are using the data, there are ways to safely filter nested ArrayCollections without modifying the original source:
http://richardleggett.co.uk/blog/index.php/2009/05/11/filtering-hierachical-data-in-flex-itree
nice !
i spend 3 hours to understand why my original array were not updated while i was apllying a filter on its Arraycollection !
so it is normal !!!!!!!!!!!!!!!!!!!!!!!!
for the people like me who want synchronise the Arraycollection and the Array source, you ca do this after the refresh :
myarray=mycollection.toArray();
but don’t forget you will lost the orginal value (that what i wanted in my case).
I have two dataServices pointing to the same destination
i got two buttons with a binding to the property text with the flag commitRequired for every DS
and if i make a change in the list associated to dsCompany , there is a change in dsCompanyTwo.commitRequired too!!
why happen this?
Best regards
Are the 2 DataService instances pointing to the same ArrayCollection instance with the fill method of each one ???
I mean. How do you fill the elements in each DataService ?? with the fill method ?? and is the fill method using the same ArrayCollection instance ?