This afternoon a user IMed me to ask for help with a ColdFusion powered Flex 2 application. He wanted to be able to perform on-the-fly filtering of data in a CF populated Flex DataGrid control. Here is the solution I sent him.
Populate the DataGrid with an ArrayCollection (converting the data to an ArrayCollection if needed). ArrayCollection has a property named filterFunction (well, technically filterFunction is a property of listCollectionView of which ArrayCollection is a subclass) which takes the name of a function to be used to filter data. Each time ArrayCollection contents are refreshed this passed function will be called, once per ArrayCollection item. If the function returns true then the item is included, if false then it is excluded. So, to filter DataGrid contents on-the-fly, simple define a filter function that performs the filtering you need, and call ArrayCollection.refresh() as the filter text changes.
Here is a complete example. In the interests of simplicity this uses a local ArrayCollection (as opposed to data returned from ColdFusion) and will run as is. ArrayCollection myData is the dataProvider for the DataGrid. Function processFilter() is the filter function, it accepts an object and returns true or false based on whether it is a match or not (this filter function looks for substrings in a single column, and this could be changed of course). The TextInput box is where filter text is entered, and the change event simply calls myData.refresh() which forces the filter function to be reapplied to the ArrayCollection.
It is worth noting that filterFunction should not be specified until the ArrayCollection has been populated (or you'll get a null reference error). So, if you are using RemoteObject to invoke a CFC method to return data to populate an ArrayCollection, you should not set filterFunction until data has been returned. As such, you may want to do this in a RemoteObject result handler.
Here's the code:
// On startup
public function initApp():void
// Set filter function
// Be careful to set filterFunction
// only after ArrayCollection has been
// Filter function
public function processFilter(item:Object):Boolean
// If no filter text, or a match, then true
|| item.name.toUpperCase().indexOf(txtFilter.text.toUpperCase()) >= 0)
<!-- Data (use ArrayCollection) -->
<mx:Object name="Ben Forta" location="Oak Park, MI" phone="(248)555-5555" />
<mx:Object name="Jane Doe" location="New York, NY" phone="(212)555-1234" />
<mx:Object name="Jim Jones" location="Atlanta, GA" phone="(414)555-1212" />
<mx:Object name="Roberta Roberts" location="Chicago, IL" phone="(312)555-4321" />
<mx:Object name="Steve Stevens" location="Boston, MA" phone="(617)555-5656" />
<!-- UI -->
<mx:TextInput id="txtFilter" width="100%"