Building a Flex Type-Ahead Text Input

0
106
6 min read

Here is an example of how google.com implements the type-ahead list using DHTML:

Building a Flex Type-Ahead Text Input

As you can see, once ‘type-ahead’ is typed into the text field , the user is given a selection of possible search phrases that google is already aware of. My intention with this article is to build a type-ahead list in Flex.

To start, lets narrow down the scope of the application and make it easy to expand on. We’ll create an application which is used primarily for searching for fruits.

Our basic Fruit Finder application will consist of a form with a TextInput field. The TextInput field will allow the user to type in a fruit name and will automatically suggest a fruit if one is partially found in our list of fruits.

1. Building a Basic Form

To start, here is what our form looks like:

Building a Flex Type-Ahead Text Input

The XML which creates this user interface is quite simple:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
layout="absolute">
<mx:Panel title="Fruit Finder">
<mx:Form>
<mx:FormHeading label="Fruit Finder"/>

<mx:FormItem label="Fruit Name">
<mx:TextInput id="fruit"/>
</mx:FormItem>

<mx:FormItem>
<mx:Button label="Search"/>
</mx:FormItem>

</mx:Form>
</mx:Panel>
</mx:Application>

You’ll notice the normal xml version declaration, the Application tag, a Panel tag and finally the Form tag. Nothing too complicated so far. If you are unfamiliar with the basics of Flex or Forms in Flex, you should take this opportunity to visit Adobe’s website to explore them. This XML code gives up 90% of our GUI. In the coming steps will have to define the elements which will make up the fruit list which will appear as a user is typing. Next, we need to define our list of fruits.

2. Adding Data to Our Type Ahead List

Now that we have the beginnings of our GUI, lets start building our fruit list. Thinking ahead for a bit, I know that we will have to display a list of fruits to the user. The simplest Flex control to use for this job is the List Control. We will be dynamically adding the List to the application’s display list via ActionScript, but for now we just need to define the data which will be displayed in the list.

We will start by creating adding a Script tag and adding an ArrayCollection to it. You will have to use the import statement to make the ArrayCollection class available to you. Our ArrayCollection constructor is passed an array of fruit names. Here is what the code looks like:

<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;

public var fruitList:ArrayCollection =
new ArrayCollection(['apple',
'orange',
'banana',
'kiwi',
'avocado',
'tomato',
'squash',
'cucumber']);
]]>
</mx:Script>

Normally defining the list of items in this way is not commonly performed. For a real world use, getting this list of items through an XML source is more likely (especially in web applications), but this will work for our demonstration.

Now that our fruit list is defined, we just need to connect it to a type-ahead list which we will create in the next step.

links:
http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_4.html
http://livedocs.adobe.com/flex/3/langref/mx/collections/ArrayCollection.html

3. Triggering the Appearance of Our Type Ahead-List

It is common in modern web applications that the type ahead list appear automatically upon the user typing. We will add this functionality to our application by using the KeyUp event. Simply put, when the user begins typing into our TextInput field we will do the following:

Determine if the type ahead list is already created. For the first key press, there will be no type-ahead list.  In this case we need to create the list, set it’s data provider to fruitList (step 2) and add it to the UI. We will also need to position the type ahead list beneath the TextInput field so that the user is properly cued as to what is happening.

To start our implementation of Type-Ahead Text Input, we use the KeyUp event. We change our FormItem tag surrounding the TextInput field to look like this:

<mx:FormItem label="Fruit Name" keyUp="filterFruits(event)">

We then define a filterFruits function like so:

public function filterFruits(event:KeyboardEvent):void{

// if the type ahead list is not present, create it
if(typeAheadList==null){

// create the list and assign the dataprovider
typeAheadList = new List();
typeAheadList.dataProvider = fruitList;

// add the list to the screen
this.addChild(typeAheadList);

}
}

In the above code we are programmatically creating a List control. Immediately assign the data provider to it. Lastly, we add the child to the application.

Our function does everything that we need it to do for a Type-Ahead Text Input with the exception of positioning the type ahead list in the correct place. Here is what our app currently looks like:

Building a Flex Type-Ahead Text Input

We are making progress, but without the correct positioning, our type-ahead list creates a bad user experience. To move this list to the correct location we need to use the localtoGlobal method to translate coordinate systems. This requires a short explanation.

Flex has multiple coordinate systems on the Flash stage that you can make use of for making your controls and components position properly. The first is call the global corrdinate system. This system starts at the upper left hand corner of the Flash stage and extends down and out. The second is called the local coordinate system which starts at the upper left hand corner of a component. There is also a content coordinate system which encompasses a components content. For our purposes we only need to focus on the local and global systems.

link:
http://livedocs.adobe.com/flex/3/html/help.html?content=containers_intro_5.html

Our goal here is to place our list directly beneath the fruit TextInput field. To accomplish this, we must first grabs the coordinates of the fruit TextInput field. Here is the code for retrieving them:

var p1:Point = new Point(fruit.x,fruit.y);

We use the Point type which receives the x and y coordinates of the fruit control. p1 now holds the points in the local coordinate system. You may ask, “what is it local to?”. In this case it is local to it’s parent container which is the FormItem. In order to convert these points to the global system we need to use to the localToGlobal method:

var p2:Point = fruit_form_item.localToGlobal(p1);

p2 now contains the converted coordinates. Note, we added the id of fruit_form_item to the FormItem Tag which is the parent of our fruit TextInput. From here we can now place the fruit List in the correct place in our application.

typeAheadList.x=p2.x;
typeAheadList.y=p2.y + fruit.height;

// set the width
typeAheadList.width=fruit.width;

Notice above that we added fruit.height to the y value of the typeAheadList. This is necessary to not block the view TextInput field. We are moving it down by n pixels, where n is the height of the TextInput field. We also set the x coordinate of our list so that it is in the correct place. Here is what the final result for this step look like:

Building a Flex Type-Ahead Text Input

LEAVE A REPLY

Please enter your comment!
Please enter your name here