Question

i want to add live searching to a list whose data provider is a very large XML. for simplicity, let's assume my XML is just a list of the world's 180ish countries:

package
{
//Imports
import fl.controls.List;
import fl.data.DataProvider;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;

//Class
public class LiveSearchXMLList extends Sprite
    {
    //Variables
    private var XMLData:XML;
    private var dp:DataProvider;
    private var list:List;

    //Constructor
    public function LiveSearchXMLList()
        {
        addEventListener(Event.ADDED_TO_STAGE, init);
        }

    //Initialization
    private function init(evt:Event):void
        {
        removeEventListener(Event.ADDED_TO_STAGE, init);

        //Download XML File
        var XMLLoader:URLLoader = new URLLoader();
        XMLLoader.addEventListener(IOErrorEvent.IO_ERROR, IOEventErrorHandler);
        XMLLoader.addEventListener(Event.COMPLETE, XMLLoaderCompleteEventHandler);
        XMLLoader.load(new URLRequest( /* COUNTRY_LIST_XML_FILE */ ));
        }

    //XMLLoader Error Handler
    private function IOEventErrorHandler(evt:IOErrorEvent):void
        {
        //Remove Event Listeners
        evt.target.removeEventListener(IOErrorEvent.IO_ERROR, IOEventErrorHandler);
        evt.target.removeEventListener(Event.COMPLETE, XMLLoaderCompleteEventHandler);

        //Throw Error
        throw(evt.text);
        }

    //XMLLoader Complete Handler
    private function XMLLoaderCompleteEventHandler(evt:Event):void
        {
        //Remove Event Listeners
        evt.target.removeEventListener(IOErrorEvent.IO_ERROR, IOEventErrorHandler);
        evt.target.removeEventListener(Event.COMPLETE, XMLLoaderCompleteEventHandler);

        //Assign XMLData
        XMLData = new XML(evt.target.data);

        createList();
        }

    //List
    private function createList():void
        {
        //Assign And Alphabetize Data
        dp = new DataProvider(XMLData);
        dp.sortOn("countryName");

        //Create List Object
        list = new List();
        list.width = 400;
        list.height = 400;
        list.x = list.y = 25;
        list.labelField = "countryName";
        list.dataProvider = dp;
        }
    }
}

the list's labelFields are populated by the XML element's <countryName> and alphabetized.

i would like to create an input text field that will listen for keystrokes and update the list according to the input string matching the countryName element values. therefore, if i enter "can" in the text field, the list will suddenly be reduced to only 5 rows:

  • American Samoa
  • Canada
  • Central African Republic
  • Dominican Republic
  • Vatican City

of course, live search should be non destructive as well - press delete once so the search field now reads "ca", which increases the 5 row list to 21 rows. (Antarctica, Jamaica, etc.)

how is this done? what is the fastest or most common approach for live searching and updating an XML provided list object?

Was it helpful?

Solution

Personally, unless you have a reason to keep your data as xml, I would transform the xml list into an arrayCollection of objects first. If you do that when you load the data it should give you some better performance overall, especially with larger data sets.

But to answer your question, I would do something like this: (this assumes you transform the xml data into an arrayCollection called _acData and you have another arrayCollection called _acFilteredData that is what the list control is bound to. Once you load up the data into _acData, copy it into _acFilteredData and then attach a function like this to your text input)

private function inpFilter_change ( e:Event ) : void
{
    var searchString:String = StringUtil.trim(inpFilter.text).toLowerCase();

    if ( searchString.length )
    {
        var newAC:ArrayCollection = new ArrayCollection();

        for each ( var tempObject:Object in _acData)
        {
            if ( tempObject.countryName.toString().indexOf(searchString) != -1 )
            {
                newAC.addItem(tempObject);
            }
        }

        _acFilteredData = newAC;

        listControl.dispatchEvent(new ListEvent(ListEvent.CHANGE)); //might not be necessary, but will force the control to update  
    }
    else
    {
        _acFilteredData = _acData;
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top