How to use the Feathers AutoComplete component

The AutoComplete class extends the TextInput component to add a pop-up list of suggestions as you type.

Screenshot of Feathers a AutoComplete component
A AutoComplete component skinned with MetalWorksMobileTheme

The Basics

First, let's create an AutoComplete control and add it to the display list:

var input:AutoComplete = new AutoComplete();
this.addChild( input );

At this point, the AutoComplete will behave like a normal TextInput without suggestions. All properties available to a TextInput (like maxChars or prompt, for example) may be used with an AutoComplete too.

Provide completion suggestions

An IAutoCompleteSource implementation should be passed to the source property to display suggestions for completion. Let's look at a couple of the classes that we can use to provide these suggestions.

LocalAutoCompleteSource

The simplest option involves passing a collection, such as VectorCollection, to LocalAutoCompleteSource. As the user types, the collection will be filtered to display appropriate suggestions.

input.source = new LocalAutoCompleteSource( new VectorCollection(new <String>
[
    "Apple",
    "Banana",
    "Cherry",
    "Grape",
    "Lemon",
    "Orange",
    "Watermelon"
]));

When one types "ap" into the AutoComplete, the list of suggestions will include "Apple" and "Grape". By default, LocalAutoCompleteSource converts each item to lowercase, and it returns any item that contains the entered text. The entered text may be in the middle of an item, as we see when "ap" matches "Grape".

If the default behavior doesn't quite fit our needs, we can use a custom compareFunction to handle the filtering. In the following example, we create a compareFunction where the entered text must be at the very beginning of the suggestion:

var source:LocalAutoCompleteSource = new LocalAutoCompleteSource();
source.compareFunction = function( item:Object, textToMatch:String ):Boolean
{
    return item.toString().toLowerCase().indexOf(textToMatch.toLowerCase()) == 0;
};

In this case, if one types "ap" using the same data provider as in the previous example, only "Apple" will be suggested. "Grape" will not be suggested because "ap" appears in the middle of the word instead of the beginning.

As you can see above, the first argument to the compareFunction is typed as Object, meaning that suggestions don't necessarily need to be strings.

URLAutoCompleteSource

In some cases, you may want to request personalized suggestions from a server instead. We can pass the text entered by the user to a backend API using URLAutoCompleteSource.

To load suggestions from the web, we need a URL. The urlRequestFunction property can be used to generate a URLRequest:

function createURLRequest( textToMatch:String ):URLRequest
{
    var request:URLRequest = new URLRequest( "http://example.com/search_suggestions" );
    var variables:URLVariables = new URLVariables();
    variables.query = textToMatch;
    request.data = variables;
    return request;
};
input.source = new URLAutoCompleteSource( createURLRequest );

The urlRequestFunction takes one argument, the text entered into the AutoComplete. We can pass that to the server to return relevant suggestions.

By default, URLAutoCompleteSource parses the result as a JSON array. If the result returned by the API looks similar to the example below, it can be parsed automatically:

[
    "adobe",
    "adobe flash",
    "adobe reader",
    "adobe creative cloud"
]

However, if the API returns data in a different format, we can use the parseResultFunction property to tell the URLAutoCompleteSource how to convert the result into something that the pop-up list of suggestions can display.

Let's create a parseResultFunction for some XML in the following format:

<search>
    <suggestion>adobe</suggestion>
    <suggestion>adobe flash</suggestion>
    <suggestion>adobe reader</suggestion>
    <suggestion>adobe creative cloud</suggestion>
</search>

In the custom parseResultFunction below, we loop through each <suggestion> element in the result and extract the string. We'll return an Array of these strings:

source.parseResultFunction = function( result:String ):Object
{
    var parsedSuggestions:Array = [];
    var xmlResult:XML = new XML( result );
    var resultCount:int = xmlResult.suggestion.length();
    for( var i:int = 0; i < resultCount; i++ )
    {
        var suggestion:XML = xmlResult.suggestion[i];
        parsedSuggestions.push( suggestion.toString() );
    }
    return parsedSuggestions;
};

The parseResultFunction may return an IListCollection implementation, such as an ArrayCollection or a VectorCollection.

Customize suggestion behavior

The minimumAutoCompleteLength property determines how many characters must be entered into the input before displaying suggestions:

input.minimumAutoCompleteLength = 3;

By default, the input will not make suggestions until at least 2 characters have been typed.

The autoCompleteDelay property determines how long to wait after the text in the input has been edited before updating the suggestions:

input.autoCompleteDelay = 0.25;

This value is measured in seconds, and the default value is 0.5.

Skinning an AutoComplete

As mentioned above, AutoComplete is a subclass of TextInput. For more detailed information about skins and font styles available to AutoComplete, see How to use the Feathers TextInput component. All styling properties are inherited by the AutoComplete class.

Skinning the pop-up list

This section only explains how to access the pop-up list sub-component. Please read How to use the Feathers List component for full details about the skinning properties that are available on List components.

With a Theme

If you're creating a theme, you can target the AutoComplete.DEFAULT_CHILD_STYLE_NAME_LIST style name.

getStyleProviderForClass( List )
    .setFunctionForStyleName( AutoComplete.DEFAULT_CHILD_STYLE_NAME_LIST, setAutoCompleteListStyles );

The styling function might look like this:

private function setAutoCompleteListStyles( list:List ):void
{
    list.backgroundSkin = new Image( listBackgroundTexture );
}

You can override the default style name to use a different one in your theme, if you prefer:

input.customListStyleName = "custom-list";

You can set the styling function for the customListStyleName like this:

getStyleProviderForClass( List )
    .setFunctionForStyleName( "custom-list", setAutoCompleteCustomListStyles );

Without a Theme

If you are not using a theme, you can use listFactory to provide skins for the pop-up list

input.listFactory = function():List
{
    var list:List = new List();

    //skin the list here, if you're not using a theme
    list.backgroundSkin = new Image( listBackgroundTexture );

    return list;
}