The best way to learn how to use the component is to use the Demo to see what options are available and then reference the source code in the examples folder to understand how it’s implemented. It’s also a good idea to skim through the methods and properties in the ASDoc file (as the demo doesn’t use every property/method available). Here are the two files: AutoComplete and AdvancedAutoComplete.
Although the component doesn’t extend from the ComboBox class, it’s designed to have as similar an interface as possible. For example, it implements the filterFunction, labelFunction and selectedItems properties as well as others.
Here’s the simplest possible implementation of the component.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:components="com.hillelcoren.components.*">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var _data:ArrayCollection = new ArrayCollection( ["one", "two", "three"] );
]]>
</mx:Script>
<components:AutoComplete dataProvider="{ _data }" />
</mx:Application>
While there are a fair number of settings you can adjust, I’d like to start by the showing the way I generally use the component.
<components:AutoComplete dataProvider="{ _data }"
prompt="Please select" backspaceAction="remove"
selectedItemStyleName="underline"/>
I’ve set three properties which I’ll review quickly here.
selectedItemStyleName: Controls the look of the selected items. There are four choices: macMail, facebook, underline and none.prompt: A string to display when no value is set.backSpaceAction: Determines what to do when a user clicks backspace. By default we focus the item (ala Mac Mail) but this can be changed to remove it.
Working with the data
Like most other Flex components you can set either the labelField or labelFunction property. By default this will control how the item is displayed through out the component (in the drop down, once selected and in the browsers).
You have a couple of choices for customizing the drop down label. You can define a dropDownLabelFunction which returns an HTML string to handle formatting the item. This is used in the email demo to display the person’s email address (ie, “Homer Simpson “) in the drop down. If you’d like greater control you can set a dropDownItemRenderer. This can be seen in the Color Chooser demo.
If multiple selection is enabled the component can contain both selected items and a search string. Because of this I’ve need to add a searchText property which can be used to get/set the search string. The text property returns a string representation of the selected items.
Related to this there are two main events which the component dispatches: change and searchChange. The change event is dispatched when the selectedItem property changes, while the searchChange event is dispatched when the search string is changed.
To filter the data you can either use the built in options by setting the “matchType” property or create a custom filter by setting a value for the “filterFunction” property. The built in options are:
beginning: Only match the beginning of the string.word: Match the beginning of any of the words in the string.anyPart: Matches any part of the string.
All of the built in options perform a case-insensitive search. Here’s how you could use the filterFunction property to implement a case-sensisitve search.
<mx:Script>
<![CDATA[
import com.hillelcoren.utils.StringUtils;
import mx.collections.ArrayCollection;
[Bindable]
private var _data:ArrayCollection = new ArrayCollection( ["ONE", "TWO", "THREE"] );
private function filterFunction( item:String, searchStr:String ):Boolean
{
return searchStr == item.substr( 0, searchStr.length );
}
]]>
</mx:Script>
<components:AutoComplete dataProvider="{ _data }" filterFunction="filterFunction"/>
To select items you have three options, you can use either selectedItem, selectedItems or selectedItemId. The first two options are pretty standard so I won’t cover them here. Setting the selectedItemId property will cause the component to search the items in the dataProvider for an object with a matching id. By defualt, it looks for a field called “id” on the item but you can set a custom field using the keyField property.
Out of the box the component requires the user to select an item from the list. You can allow the user to enter their own values by setting allowNewValues to true. You can then control whether or new the new items are editable by setting the allowEditingNewValues property. Additionally, you can set the allowDuplicates property to control whether or not to allow an item to be selected more than once.
A common question is how to use the component with data returned from the server. The best practice is to use a change listener. Once the user has entered enough characters fire off your data request. Once the data has been returned and passed to the dataProvider you can call the search() method to tell the component to filter the items and display the drop down. You can check out the DynamicData.mxml file in the examples folder to see the details.
You can use either an ArrayCollection or an XMLListCollection as the dataProvider. I showed you an example with an ArrayCollection earlier on, here’s an example using an XMLListCollection.
<mx:XML format="e4x" id="xml">
<items>
<item>one</item>
<item>two</item>
<item>three</item>
</items>
</mx:XML>
<mx:XMLListCollection id="xmlList" source="{ xml.item }"/>
<components:AutoComplete dataProvider="{ xmlList }"/>
Usability settings
Multiple Selection
This is the one feature which separates the component from other the AutoCompletes out there, setting the allowMultipleSelection to true enables the user to select more than one value. The AdvancedAutoComplete extends this feature by adding a selectionLayout property which when set to vertical causes the selected items to be displayed in a List component.
AutoSelect
The AutoSelect functionality will automatically select an item if it matches a case-insensitive string comparison and is the only match found. This feature can be disabled by setting autoSelectEnabled to false.
If you’d like to use a custom function to determine if an item should be auto-selected you can set a value for the autoSelectFunction property. Here’s an example where we use this property to auto-select once when there is a single match. For example, typing “o” will select “one” right away.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var _data:ArrayCollection = new ArrayCollection( ["one", "two", "three"] );
private function selectFunction( item:String, searchStr:String ):Boolean
{
return true;
}
]]>
</mx:Script>
<components:AutoComplete dataProvider="{ _data }" autoSelectFunction="selectFunction" />
Clear Icon
The core of the component is the PromptTextInput class. This class provides two main features: the prompt and the clear icon. We covered the prompt earlier but the clear icon is a little gray x icon which appears if there is text in the component. Note, this feature only works if allowMultipleSelection is set to false.
Drop Down
The number of items displayed in the drop down is controlled by the dropDownRowCount property. By defualt, the width of the drop down will
be set to match the width of the TextInput. However this can be overriden using the dropDownWidth property. On the topic of the drop down, you can use the showDropDown, hideDropDown and isDropDown visible to show/hide the drop down.
AdvancedAutoComplete
The challenge in building a component with lots of features is keeping it as streamlined as possible. In order to support adding more advanced functionality while not bloating the component I’ve created an AdvancedAutoComplete class which extends the AutoComplete component.
Selection Layout
As discussed earlier, setting the selectionLayout to vertical causes the items to be displayed in a List. When using the vertical layout you can use the showRemoveButton property to control whether or not to show a remove button.
Browsing
This can be enabled by either setting the showBrowseButton property to true, or by adding an options to the action menu (as is demonstrated in the Color Chooser Demo). By default we show a pop window which contains a searchable DataGrid. You can control which fields of the data to display in the grid using the browserFields property. If multiple selection is enabled, you can set the useListBuilder property to true to display a two column browser instead. If you’d like to implement your own browser you can either extends one the existing ones are create a component which implements the IBrowser interface. You’ll then need to set the browserClass property to your new class.
Ordering
If the selectionLayout is set to vertical you can enable the user to order the items in the list by setting the showOrderButtons property to true. If using the List Builder the ordering buttons will also be displayed in it.
Actions Menu
To enable the action menu you need to set a value for the actionsMenuDataProvider. This is just a regular Flex Menu component so all the usual features are supported (ie, using checkboxes). Here’s a link to the supported menu attributes. You can see an example of how to use this feature in the code for the AdvancedDemo. If enabled the menu can be displayed by pressing the down button while the component has focus.
Odds and Ends
Custom Skins
The selected items are simply buttons, this means it’s pretty easy to change the look and feel using skins. The styles which the component comes with (macMail, facebook, etc) are all implement using skins. It’s possible to define your own custom skin. If you’d like to implement it you can check out the CustomSkin.mxml file in the examples folder.
First Class Components
The component is made up of a number of classes. Some of these classes are useful in their own right. I consider the following three classes to be first class components:
- PromptTextInput: This is a TextInput with two additional features, you can set a prompt which will appear when no value is set and a clear icon will appear when there is a value set and the mouse is over the component.
- ListBuilder: This is a two column browser which can be used to add/remove items from a list.
- CloseableTitleWindow: Adds a key listener to the TitleWindow which enables the user to click the ESC key to close it.
Utility Classes
The com/hillelcoren/utils folder contains a couple of helper classes. There are some useful functions here which you may be able to use elsewhere in your applications. Some examples include a function to compare if two ArrayCollections are equal and functions to convert string to/from camel caps.
Validating
You can use a regular validator to make sure that a value is selected. Here’s a simple example demonstrating how to implement it.
<mx:Validator source="{ autoComplete }" property="selectedItem"/>
<components:AutoComplete id="autoComplete" dataProvider="{ _data }"/>
Inline Button
You can use the inlineButton property to set a button to appear at the end of the component. This feature is used in the AdvancedAutoComplete for the button used to display the actions menu. Here’s an example of how you can use this property to display a button which causes the drop down to appear (ala a regular ComboBox)
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var _data:ArrayCollection = new ArrayCollection( ["one","two","three"] );
private function handleButtonClick():void
{
if (autoComplete.isDropDownVisible())
{
autoComplete.hideDropDown();
}
else
{
autoComplete.search();
autoComplete.showDropDown();
}
}
]]>
</mx:Script>
<components:AdvancedAutoComplete id="autoComplete" dataProvider="{ _data }">
<components:inlineButton>
<mx:Button skin="mx.skins.halo.ComboBoxArrowSkin" click="handleButtonClick()"/>
</components:inlineButton>
</components:AdvancedAutoComplete>
That about does it, hopefully you found this useful. I plan to continue to improve the documentation over time. If anything here is unclear, or if there are other areas you’d like me to cover please post a comment and I’ll update the page.
Best,
Hillel
when you try to add a new tag and want to name it “star”. but have already “starfish” registered as tag. it automatically selects this one instead of creating a new one. Is there a key or separator to avoid automatic selection? thanks for this excellent component, Hillel !
Delimiter is not working for me. I’m using the latest version of AutoComplete built on Flex 4 SDK.
Could you please provides some more details, are you setting a custom delimiter or are using the default (commas). Also, what about it exactly isn’t working.
Hi Hillel,
Thanks for the prompt reply, instead of the default delimiter which is a comma, I was ask to change it into semi-colon so I set the value of the delimiter property of the AutoComplete component into a semi-colon ( ; ) but it did not work. It still uses the comma. By the way thank you for sharing this great component it really helps me a lot in most of my projects.
You’re absolutely correct, I’ll include a fix for this in the next version. For now to fix it you’ll need to use the source and replace the comma in line 61 of classes/IconButton.mxml in the commitProperties function.
Thank you very much for this quick solution. Good thing I also have the source file. Have nice day Hillel.
How can I change the sort order of items in the popup browser?
I have:
Room 1
Room 2
….
Room 9
Room 10
Room 11
But – they display alphabetically, I want them to display in the natural order of the list.
You’ll need to apply a custom sort function to your dataProvider. In order to sort numerically you’ll need to remove the “Room ” part of the string and then convert the remaining characters to numbers.
Hi, Hillel! Once again, thank you for great component!
I am facing a small problem.
When I create custom skin for selected item, and then try to use it like this:
selectedItemStyleName=”autoCompleteSelectedItemSkin”
Compiler geves me an error:
“Invalid value: autoCompleteSelectedItemSkin. It must be one of macMail, facebook, underline, none.”
Flex SDK 4.5.1.
Can you please give me some advice?
I’ve managed to ovrriede the default style by adding by adding the same style name in my main application css file, that solved the problem.
Thanks for letting me know you worked it out.
Best,
Hillel
This component is awesome! Thanks for sharing!
I have only 1 question – how can you preselect an item (I mean, let’s say this autocomplete is a part of a contact form and I want to use the form to edit the data taken from the db – the user hits edit button, and the contact form appears with all fields populated and ready for editing. How do I ‘tell’ the component to preselect one specific dataprovider (ArrayCollection) item?
autoComplete.selectedItem = (the item you want to select)
forgot to mention that I’ve already tried that, but I might be doing something wrong – could you provide an example of what should be there instead of “(the item you want to select)”. I have an array collection called citiesAC with ID and City in it (data taken from sqlite) – could you tell me how it should look like if I wanted to have any item preselected e.g. pair ID=2 and City=”London” ?
In that case you could use selectedItemId
got it sorted out! Thanks Hillel!
Hi Hillel,
I have 1 more question – how do I retvieve the selected item’s id after i ‘manually’ (using code) preselect some item. For example, I have an ArrayCollection citiesAC with 2 fields ID and City and i do:
autoComplete.dataProvider = citiesAC;
autoComplete.selectedItem = “London”
and then when I do:
trace(autoComplete.selectedItemID)
i always get NaN instead of 2 as assigned in the Array Collection. Any ideas how can I retrieve the ID after I manually set the selectedItem property to any string?
Try calling validateNow()
unfortunatelly it didn’t help. When I was debugging the app i saw that after calling validateNow() the only thing that changed was selectedItem and _selectedItem. SelecteditemId with no changes. Got any other ideas?
Could you then use selectedItem.ID
Unfortunatelly that didn’t work neither. Anyway I did a little workaround to solve this – I searched the dataProvider manually comparing it to the city I wanted to preselect and then setting the actual autoComplete field using the selectedItemId that was assigned to the found item and everything works perfect.
Maybe a thing to consider in future releases of the component would be automatic browsing thru the dataprovider to find the corresponding ID to a preselected item using String (for example autoComplete.selectedItem = “London”). That would make things easier a bit i think.
Anyway thanks for your help! Cheers!
Hi Hillel,
This component is very good! I want to know how to copy the selectItem.
Thanks,
John
I’m sorry, I’m not sure what you mean. Could you please try explaining it another way.
Hi Hallel,
I have doubt related to Auto complete…
i have tow auto complete text box ( say book name and author)
Book name ( ABC) selected from listing (ABC,DER,FEB) and author (BEL) also selected from authors listing(DEL,BEL,KAL)…
When I focus the third textBox, popup should appear with the listing (ABC,BEL) of above text box answers…
Can you please provide me a sample source code…
If you haven’t done so already you may want to take a look at the files in the example folder.
Hi Hillel
How can I set the fontFamily of the AutoComplete prompt?
I went through the Documentation with no luck
can you please assist?
cheers
Which version of Flex are you using. With 3.x just setting fontFamily=”” appears to be working for me. I did find another user who posted a comment related to embedded fonts in Flex 4.5 though… http://hillelcoren.com/flex-autocomplete/comment-page-5/#comment-6454.
Hi Hillel and thank you for replying so soon
I’m using flex 3
so yes, of course I set the fontFamily style, and indeed it is working
for the input text when I’m typing in it
though when I focus out, the prompt is rendered in some other system font with Italic fontStyle…
does the AutoComplete component uses two different text components for the prompt and the textInput?
cheers
Yariv
The text input and the prompt are the same component. The class is called PromptTextInput and it should use the same font for the prompt just italicized. If you don’t want the font to be in italics you’ll need to use the source and modify it. The italics are set in the showPrompt function.
that explains it, I’m using an embedded font which I haven’t embed its italic type. thanks for that.
That would explain it… happy to help
Been reading through your documentation and although it is very helpful, just wanted to point out that the your coding examples are being HTML encoded making it very hard to read through the code quickly. Hopefully this can be remedied to make it easier for users of your components to read through your documentation.
Thanks for pointing that out. I host my blog on wordpress.com and in the past they’ve changed how they display code. I’ve fixed the code examples in the documentation.