Powerful filtering on collections in Flex

People search for things all the time. It is in our genes and we use tools to achieve our goals. On the internet a lot of us use Google to find what we need. So most of us are familiar with Google search techniques. Now some of these search techniques are put into a very powerful filter function for Flex.

The features supported

This filter has an ignore list too. If you add words to it, you can make it even more Google search like. For example Google ignores words like “a” or “the” to help their users in their quest for information.

Of course you do not have to use features like the ignore list, the synonyms and the case sensitive option. If you do not use these features you still have a very powerful filter that’s easy to implement. A nice feature to extend this filter with in your application would be to allow the user to select the columns to search in. This column selection is not in the demo application, but my guess is you are perfectly capable to do it yourself.

The source

The only code shown is the code of the demo application, but you can download the full source. The other code is not put on the page, because it are too many files to put on a webpage. Do not let this scare you, because it is not that much or that complicated.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
			   creationComplete="creationCompleted(event)"
			   width="400" height="265">
	<fx:Script>
		<![CDATA[
		import mx.collections.ArrayCollection;
		import mx.events.FlexEvent;
		import nl.vanhulzenonline.collections.filter.Evaluator;
		import nl.vanhulzenonline.demo.Album;
		import spark.components.gridClasses.GridColumn;
		
		private var _collection:ArrayCollection;
		private var _evaluator:Evaluator = new Evaluator();
		
		private function creationCompleted(event:FlexEvent):void
		{
			_collection = Album.collection;
			_collection.filterFunction = filterCollection;
			
			_evaluator.synonyms["four"] = new ArrayCollection(["4"]);
			
			grid.dataProvider = _collection;
		}
		
		private function filterChanged(event:Event):void
		{
			update();
		}
		
		private function update():void
		{
			_evaluator.prepare(filter.text);
			_collection.refresh();
			
			formula.text = (_evaluator.tree) ? _evaluator.tree.toString() : "";
		}
		
		private function filterCollection(data:Object):Boolean
		{
			var labels:ArrayCollection = new ArrayCollection();
			for (var i:int; i < grid.columns.length; i++)
			{
				labels.addItem(
				  (grid.columns.getItemAt(i) as GridColumn).itemToLabel(data));
			}	
			return _evaluator.evaluate(labels);
		}
		
		private function caseSensitiveFilterChanged(event:FlexEvent):void
		{
			_evaluator.caseSensitive = caseSensitiveFilter.selected;
			update();
		}
		
		]]>
	</fx:Script>
	
	<s:VGroup left="5" right="5" bottom="5" top="5" >
		<s:TextInput id="filter" width="100%" change="filterChanged(event)" />
		<s:CheckBox id="caseSensitiveFilter" label="filter case sensitive" 
			valueCommit="caseSensitiveFilterChanged(event)" />
		<s:DataGrid id="grid" width="100%"  height="100%" >
		</s:DataGrid>
		<s:Label id="formula" />
	</s:VGroup>
</s:Application>