« Rich Interactive Applications restyling: A matter of usability | Main | Weborb .NET: a simple example »

Multiple field filtering with ArrayCollection

The flex class ActionScript has a very useful method, filterFunction, that allows to pass as a parameter another function, to be applied as a filter for the data. The filter is effectively applied only after we invoke refresh() on the ArrayCollection. The result is well known: the collection will only show those items that match the filter function, while all elements, filtered or not, can be accessed from the list or source properties of the collection.

Suppose we have a collection of objects with many properties, and we want to filter on a few properties at a time, not always the same. For example we could have the class AirplaneReservation, with a subset of the properties similar to:

public var firstName:String;
public var lastName:String;
public var gender:Number;
public var reservationDate:Date;
public var destination:String;
public var departure:String;
public var seat:String;
public var menuType:Number;

and we want to filter on whatever combination of properties, using a Form component to display them all to the user.

We could create as many filter functions as our use cases, which can be a lot to handle, or we could use different approaches, tweaking the flex framework to our needs. Rotundu made a post about multiple field filtering, that can be found here, by extending the ActionScript class and adding an array of filter functions, to be eventually applied as a single one.

The approach illustrated here is similar, in that it uses many filter functions, but different in that it does not extend ArrayCollection and associates a filter function with a field of our collection object.

We can create the Form component, with input fields for every filter (TextInput, NumericStepper and so on) and, on the change event, call a single function:

<mx:TextInput id="firstName" change="applyFilter('firstName', firstName.text)" />

In most of the cases we can use a single applyFilter() function, that receives in input the name of the property to be filtered and its value. This function will then create an ad hoc filter function and apply it to our collection. We will make use of a Dictionary to associate a field with its filter function:

private function applyFilter(field:String, value:*):void {
var f:Function;
if ((value == null) || (value.length == 0))
f = null;
else {
f = function(item:Object):Boolean {
if ((item == null) || !item.hasOwnProperty(field))
return false;

if (item[field] is Boolean)
return Boolean(item[field]) == value;
if (item[field] is Number)
return Number(item[field]) == value;
if (item[field] is String)
return String(item[field]).localeCompare(value) == 0;
if (item[field] is Date)
return Date(item[field]).time == Date(value).time;
// any other object:
return item[field] == value;
};
}

_filterFunctions[field] = f;

_collection.filterFunction = multipleFilter;
_collection.refresh();
}

This will create a filter function for the field received in input, store it in the Dictionary so that it will be available for multipleFilter():

private function multipleFilter(item:Object):Boolean {
for (var key:Object in _filterFunctions) {
var f:Function = _filterFunctions[key];
if ((f != null) && !f(item))
return false;
}

return true;
}

We can now filter as many fields as we want, at the same time, using these two functions only. The applyFilter function can easily be adapted to custom business objects, by means of object polymorphism and interfaces (Java’s Comparable is a good example).

TrackBack

TrackBack URL for this entry:
http://blog.comtaste.com/mt-tb.cgi/92

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

About

This page contains a single entry from the blog posted on April 27, 2009 9:07 AM.

The previous post in this blog was Rich Interactive Applications restyling: A matter of usability.

The next post in this blog is Weborb .NET: a simple example.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.33