Flex Filtering Long Lists
If you have a list box with a large number of items in it it can be hard for someone to find the item in the list that they need. One way around this is you add a filter on the list box.
Here's how it's done.
First off it best if you use an ArrayCollection as they provide a built in method of filtering. You can set up a filter function on an ArrayCollection that looks at every item and returns true or false if you want the item to be in the list. Refresh the list and every item is checked again. If you want the original list back just remove the filter function and refresh the list and all is back the way it was.
The other ingredient is a text field that that as you type takes the contents of the field and applys it as a filter on the list.
Here's the code.
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()" viewSourceURL="srcview/index.html">
3 <mx:Form>
4 <mx:FormHeading label="Select Suburb" />
5 <mx:FormItem label="Search" direction="horizontal">
6 <mx:TextInput id="filter" change="setFilter()" />
7 <mx:Text text="{locations.length} suburbs found" />
8 </mx:FormItem>
9 <mx:FormItem label="Suburbs">
10 <mx:List dataProvider="{locations}" rowCount="10" width="300" labelFunction="locationPostcode" />
11 </mx:FormItem>
12 </mx:Form>
13
14 <mx:Script>
15 <![CDATA[
16 import mx.collections.*;
17
18 [Bindable] private var locations:ArrayCollection = new ArrayCollection();
19
20 private var text:String = "";
21 private var loader:URLLoader;
22
23 public function init():void {
24 // load postcode csv file
25 this.loader = new URLLoader();
26 this.loader.dataFormat = "text";
27 this.loader.addEventListener("complete",this.loaded);
28 this.loader.load(new URLRequest("postcodes.csv"));
29
30 // sort by location
31 var sort:Sort = new Sort();
32 sort.fields = [new SortField("location")];
33 this.locations.sort = sort;
34 this.locations.refresh();
35
36 this.locations.filterFunction = filterLocation;
37 }
38
39 // display suburb and postcode
40 private function locationPostcode(data:Object):String {
41 return data.location + " (" + data.postcode +")";
42 }
43
44 // set up filter on location array collection
45 private function setFilter():void {
46 this.text = filter.text;
47 this.locations.refresh();
48 }
49
50 // called when postcode file loaded
51 private function loaded(evt:Event):void {
52 var file:String = this.loader.data;
53 var lines:Array = file.split('\r');
54
55 // covert file into an array collection
56 for (var i:Number = 1; i < lines.length; i++)
57 {
58 var data:Array = lines[i].split(',');
59 var item:Object = new Object();
60
61 item.postcode = data[0];
62 item.location = data[1];
63
64 this.locations.addItem(item);
65 }
66 }
67
68 // filter array collection by what user types
69 private function filterLocation(item:Object):Boolean {
70 if (item.location.toLowerCase().indexOf(this.text) >= 0) {
71 return true;
72 }
73 else {
74 return false;
75 }
76 }
77 ]]>
78 </mx:Script>
79</mx:Application>
The code reads an CSV file that contains a list of all suburbs/postcodes in Australia.
This technique can be easily expanded to search on multiple fields. For example you could have a list of locations and filter on the name, the address, the city and/or the postcode
Now you might think that this method is going to be a little slow. It's not! It can easily handle lists of 1,000 or 2,000 items and even up to 50,000 items without any noticeable performance issues. The postcode example contains more than 16,000 locations. Of course downloading and sorting data of that size may cause a little delay before the list box is populated.
Here's the running code (right click to view source and/or download):
There are no comments for this entry.
[Add Comment] [Subscribe to Comments]