Flex AutoComplete Component: a new take on an old standard…

While there are a couple of other AutoComplete components out there (most notably the ones from the Flex Team and kuwamoto.org), neither of them had the features we were looking for. I struggled for a while trying to extend them but it just wasn’t working.

One of the main features we needed was for the component to show the part of the string which matches the search term. We also needed it to support selecting multiple items as well as creating an ordered list.

Latest version

As you can see in the demo, there are four main boolean properties which control how the chooser works:

  • isBrowseable: This will display a ‘Browse’ button to the right of the TextInput. If the user clicks it they will be presented with either a searchable DataGrid or a list builder (see below).
  • isMultiSelect: This enables selecting multiple values.
  • isOrderable: This makes the items in the list orderable. It provides buttons to reorder them as well as enabling drag-and-drop.
  • useListBuilder: If this is set to true, when clicking the browse button the user gets a List Builder rather than the DataGrid (note: this requires isBrowseable and isMultiSelect to be true).

Here are the other main properties:

  • labelField: Which property of the data objects to use when displayed in the TextInput and the Lists.
  • labelFunction: In place of the labelField you can specify a function for determining the string to display.
  • dropDownLabelFunction: A reference to the function used to display the matched items in the dropdown. It supports using HTML (which can be used to highlight the part of the string which matches the search pattern).
  • prompt: The message which is initially displayed in the TextInput.
  • filterFunciton: A reference to the function used to search when entering text into the TextInput. The function is passed the object being checked along with the search string
  • isEqualFunction: A reference to a function which can be used to determine if the search string should be considered equal to the object (if it returns true it will automatically select the item).

The bare minimum required to use the component is to set the dataProvider property to an ArrayCollection of objects and specify a value for labelField.

The code for the demo is pretty straight forward.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:hc="com.hillelcoren.components.*"
	width="550" height="400"
	initialize="init()">

	<mx:Script>
		<!&#91;CDATA&#91;
			import mx.collections.ArrayCollection;

			&#91;Bindable&#93;
			public var colors:ArrayCollection;

			private function init():void
			{
				colors = new ArrayCollection(
				&#91;
					{ "name":"Almond", "hex":"#C5E17A" },

					...

					{ "name":"Yellow Orange", "hex":"#FFAE42" }
				&#93; );
			}			

			private function handleChange():void
			{
				var color:Object = chooser.chosenItem;

				if (color != null)
				{
					setStyle( "backgroundColor", color.hex );
				}
			}
		&#93;&#93;>
	</mx:Script>

	<mx:Panel width="100%" height="100%" title="Chooser Demo"
			paddingBottom="20" paddingTop="20" paddingLeft="20" paddingRight="20">
		<mx:HBox>		

			<mx:VBox horizontalAlign="left">
				<mx:CheckBox id="browesable" label="Browesable"/>
				<mx:CheckBox id="multiselect" label="Multiselect"/>
				<mx:CheckBox id="orderable" label="Orderable" enabled="{ multiselect.selected }"/>
				<mx:CheckBox id="listBuilder" label="List Builder" enabled="{ multiselect.selected }"/>
			</mx:VBox>		

			<hc:Chooser id="chooser" dataProvider="{ colors }" labelField="name"
				prompt="Choose your favorite Crayola crayon" width="300" change="handleChange()"
				isBrowseable="{ browesable.selected }" isMultiSelect="{ multiselect.selected }"
				isOrderable="{ orderable.selected }" useListBuilder="{ listBuilder.selected }"/>					

		</mx:HBox>
	</mx:Panel>
</mx:Application>

I consider this to be a version 0.9. It seems to work pretty well but I’m sure there’s a bug or two hiding in there. There are also a couple of more features I’d like to implement.

There’s no copyright… please use the code freely. I just ask that if you come up with any improvements you email them back to me.

Hope you find this component useful,
Hillel

95 thoughts on “Flex AutoComplete Component: a new take on an old standard…”

  1. This has been extremely useful to me too.

    One thing I haven’t worked out yet is how to get the datagrid in the browse feature to *not* sort alphabetically (I want a column named “code” to display before one called “address”, for example).

    Thank you

    1. Pete,

      You can apply a sort to the dataProvider which should sort it in the datagrid. The only catch is the sort will also be applied in the search results in the dropDown.

      Hope this helps,
      Hillel

  2. Hi!
    Your component is just incredible! I love it! I use it in my applications and it works really good! Just one thing. When drop down is opened and the AutoComplete is in a scrollable parent container, the drop down position moves with th scroll position. It doesn’t stay fixed. Weird behavior! Thanks for all!

    1. Daniel,

      I think the real problem here is that when you click outside the component (ie, to scroll) the dropDown needs to be hidden. I was using the hitTestPoint function to check if the user clicked outside the dropDown but it looks like it doesn’t work if you click just below the list. I’ve changed the code to fix this and have checked it in to the google code site.

      Let me know if this resolves your issue.

      Thanks,
      Hillel

  3. Hi Hillel!
    Thanks for the reply! I just forgot to mention that I was using the mouse wheel to scroll. I tried to put a MouseEvent that manage the wheel, but looks like it is never fired. It is a minor bug! Thanks for your awesome work!

  4. i’m new to flex starting with flex 3 for 1 month. is there a very simple way to do this autocomplete stuff or anything in flex i.e. just insert an object from the tool bar and functions just work. is flex called open source because everyone is figuring out to do something and passing it on to everyone else.

    1. Jim,

      That’s a difficult question to answer. Although Flex is designed to be quick to get up and running it’s generally not the case that you can drop something in and it’ll just work. I’ve found the Flex community to be extremely helpful when trying to figure things out. If you have questions the best place to post them is the Flex forum.

  5. Hi Hillel, Great component.

    For my project, i need to have rounded edges of the text box. If i select corner radius = 9, i can only see the focus as rounded.

    I applied following style:
    AutoComplete{
    borderStyle: solid;
    borderColor: #777777;
    borderThickness: 1;
    cornerRadius: 6;
    backgroundAlpha: 1;
    }

    But this gave me rounded edge imposed on square edge.. This styling fixes rounded edges of textinput but is however not working for AutoComplete.

    PLease Help ASAP.

    Thanks.

  6. Hi Hillel
    First of all thanks for sharing your wonderful component with us…
    and excuse me for bothering you with beginner questions.
    I’d like to extend the disable duplicates functionality like this:

    imagine we have following array in the ColorDemo:

    colors = new ArrayCollection(
    [
    { “name”:”aaa”, “hex”:”groupOne” },
    { “name”:”bbb”, “hex”:”groupOne” },
    { “name”:”ccc”, “hex”:”groupOne ” },
    { “name”:”ddd”, “hex”:”groupTwo” },
    { “name”:”eee”, “hex”:”groupTwo” },
    { “name”:”fff”, “hex”:”groupTwo ” },

    ] );

    Supposed I clicked an entry of groupOne
    How can I disable the rest of groupOne

    I found the following function in autocomplete.mxml:

    private function checkIfDuplicate( searchFor:Object ):Boolean
    {
    if (_allowDuplicates)
    {
    return false;
    }

    var count:int;

    for each (var item:Object in _selectedItems)
    {
    if (item == searchFor)
    {
    count++;
    }
    }

    if (count > 1)
    {
    silentlyRemove( item );
    return true;
    }

    return false;
    }

    How can i achieve that the hex field of the array is checked for duplictes instead the of the name field?
    or even better both of them?
    Thanks in advance…
    Martin

    1. Martin,

      The checkIfDuplicate function should really be protected. You’re going to need to use the source and modify the logic in the function to “if (item.hex == searchFor.hex)”

  7. Hi Hillel,

    Can we set the separator that triggers the auto-completion search? For example, after I typed in a new value, I have to input a comma in order to start another search. How can I use space instead of comma? The reason I am asking is I would like to use auto-complete to allow user to input an expression. The extra commas would confuse the expression.

    Thanks for your time

    -Bo

  8. Hi Hillel
    All the best for 2010…
    Currently I am develloping an application where i use
    your color_demo and your email_demo.
    to move the values I collected via your autocomplete component
    to my database I first of all have to sort them to an array and splice them to the
    position that maches the database table’s fields.

    colors = new ArrayCollection(
    [
    { “name”:”wert1″, “hex”:”1″, “nr”:”10″, “val”:”1″ },
    { “name”:”wert2″, “hex”:”1″ , “nr”:”10″, “val”:”2″},
    ..etc

    I simply recycled your function for changing the bg color,
    to splice the contents of the autocomplete box to an array (to transmit it to a database later)

    private function handleAutoCompleteChange():void
    {
    var color:Object = autoComplete.selectedItem;

    if (color != null && color.hasOwnProperty( “hex” ))
    {
    //Application.application.setStyle( “backgroundColor”, color.hex );

    Application.application.antworten.splice(color.nr, 0, color.val);
    trace(Application.application.antworten);
    }
    }

    this works.

    But how could I achieve to do the same when something is removed via backspace?
    I mean, replacing the Value in my Array at Position “color.nr” with a default value..

    Sorry for asking beginner Questions

    thanks
    Martin

  9. Hello Hillel
    very helpful component u have created.
    But I am new in flex field and still I am having some problem with it.In textInput box a grayBOx is coming inside textInput box(or more clearly autocomplete box), I want the component to look exactly like textInpt after selecting an item and don’t want to have that gray box inside what I can do for it? Please reply ASAP.

  10. I just want to know that weather your component is free to use or it require any Licence. Also I would require source code or SWC file if it is free to use. Please let me know from where we can download the same.

    Thank in Advance.
    Lakhan

  11. Hello
    I’m from Brazil, use the Chooser component, but I have a difficulty using the property isBrowseable = “true”, like that when I could use this property to limit the columns in the DataGrid that opens, just put the ID and Description of the object. and I also have the difficulty to rename the column of the DataGrid headerText that opens on top, can you help me?

    Felipe
    Brazil

    1. Felipe,

      To specify which properties to show in the dataGrid and set the headers you can use the following (note: make sure you’re using 1.1 version of the component).

      autoComplete.browserFields = [{field:”id”,label:”ID”}];

      Best,
      Hillel

  12. this is indeed a great component ..
    i was just wondering … is there a way to populate the “textinput” with data coming from a database? should i convert the lastResult into an Array Collection? im quite lost about this pls do help .. tnx .. ^^

    1. mike,

      I’d start by checking out the DynamicData.mxml file in the examples folder of the zip. Let me know if you have any trouble getting it working.

Leave a comment