Filtering Collections

Example

This article is a basic introduction to Collection filtering.

This example uses 2 ComboBoxes. You may have seen ComboBoxes like these on automotive web sites. One ComboBox contains a list of makes (Ford, Kia, Volkswagen, etc.) and the other ComboBox contains a list of models (Mustang, Passat, A4, etc.). The second ComboBox however, only displays models which come from the maker choosen in the first ComboBox. In other words, the models are filtered based on the selection of the make.

Figure 1: The Make ComboBox: Figure 2: The Model ComboBox:

Run the Example

Suppose you have a database that you query for all of the auto makers and all of the models. Normally you might get just the makers and fill the first ComboBox. When the user picks a make, another query is made for all of the models that match the maker. In this example, ALL of the models are returned, each keyed with their maker. Something like:

{make:"Ford", model:"Mustang"},
{make:"Ford", model:"Fusion"},

{make:"Volkswagen", model:"Beetle"},
{make:"Volkswagen", model:"Passat}

Suppose the data were assigned to ArrayCollections when retrieved from the server:

[Bindable] private var makeCollection:ArrayCollection;
[Bindable] private var modelCollection:ArrayCollection;

private var queryResultHandler( event:ResultEvent ) : void
{
     makeCollection = new ArrayCollection( event.result.makes );
     modelCollection = new ArrayCollection( event.result.models );
}

and these Collections are the dataProviders for the ComboBoxes:

<mx:ComboBox id="makeCombo" prompt="Select" dataProvider="{makeCollection}" labelField="make" />
<mx:ComboBox id="modelCombo" dataProvider="{modelCollection}" labelField="model" />

At this point the modelCombo shows ALL of the models – no matter what is selected in the makeCombo. This is not what you want. Initially, without anything selected in the makeCombo, the modelCombo should be empty.

filterFunction

To do this you need two things: filter criteria and a filter function.

The filter criteria for this example is simple: the selection of the makeCombo. The filter function is almost as simple:

private function filterByMake( item:Object ) : Boolean
{
     return( makeCombo.selectedItem.make == item.make );
}

Assuming that the item parameter in the filterByMake function is an element of the modelCollection, this function returns true whenever the item’s make property value matches the makeCombo’s selectedItem’s make property value.

The filterByMake function needs to be assigned to the modelCollection as its filterFunction:

modelCollection.filterFunction = filterByMake;

The final piece is triggering the filter by calling the Collection’s refresh() method:

modelCollection.refresh();

Putting it all together

Now that you have the parts, here is how it all fits together with some missing statements to make it work.

[Bindable] private var makeCollection:ArrayCollection;
[Bindable] private var modelCollection:ArrayCollection;

private function queryResultHandler( event:ResultEvent ) : void
{
     makeCollection = new ArrayCollection( event.result.makes );
     modelCollection = new ArrayCollection( event.result.models );

     // set the filterFunction and refresh the data so that the collection is initially empty
     // (there is no selection on the makeCombo so the test fails for every item)

     modelCollection.filterFunction = filterByMake;
     modelCollection.refresh();

}

private function filterByMake( item:Object ) : Boolean
{
     var makeItem:Object = makeCombo.selectedItem;
     if( makeItem == null ) return false;

     return( makeItem.make == item.make );
}

<mx:ComboBox id="makeCombo" prompt="Select"
         dataProvider="{makeCollection}" labelField="make"
         change="modelCollection.refresh(); modelCombo.selectedIndex=-1" />
<mx:ComboBox id="modelCombo" dataProvider="{modelCollection}" labelField="model" />

When a selection is made on the makeCombo, the change event handler calls the modelCollection’s refresh() function and clears the selection from the modelCombo. This runs all of the modelCollection items through the filterFunction, filterByMake(), screening out all those models that do not have the same maker.

The modelCombo dropdown list is automatically updated because it is data-bound to the modelCollection.