Flex AutoComplete: Version 1.0

It’s been about a year since first creating the component. I’ve been using it extensively in the applications I work on and it’s been downloaded thousands of times. At this point I’m pretty confident in saying that it works reliably.

Latest version

If you’re already using the component you probably noticed that there’s now a “Latest version” link (rather than the old Demo and Download links). I’ve decided to set up a permanent page on my blog for the component. The important info (ie, the component’s license) is currently scattered amongst the past posts, this way I can keep everything together in one place.

Here’s what’s changed in this release

  • Added support for XMLListCollections: You can now use either an ArrayCollection or an XMLListCollection as the dataProvider.
  • ListBuilder is now a first class component: I’ve refactored the code to support using the ListBuilder on it’s own.
  • Added browserFilterFunction: I’ve added a browserFilterFunction which enables applying a separate filter which is applied to the results shown in the browser. I sometimes show a mix of items in the component. I use this to offer multiple browse options in the actionMenu in the AdvancedAutoComplete.
  • Bug fixes and tweaks: As always, I’ve gone through all of the comments and fixed any issues people have found.

Thanks to e/o who’s spotted bugs, suggested improvements and just been supportive in getting the component to this state. There’s no doubt in my mind that sharing the component with the Flex community has made it far better than it otherwise would have been.

Best,
Hillel

69 Responses to “Flex AutoComplete: Version 1.0”

  1. Ján Regeš Says:

    Hi!

    Your AutoComplete component is great, but i discovered some issue. When i set in Project properties “Required flash version” to 10+ (10.0.0 or 10.0.22), submit of found autocomplete-item by ENTER doesn’t work (in property “selectedItem” is object of selected item, but text-input view is empty). When i set required flash version to 9.0.124, all works fine.

    Thank you for your response and good luck! :-)

    My source code:

    • Hillel Says:

      Ján,

      Thanks very much for pointing this out. I’ve been able to track this down to the change handler for the TextInput. It looks like if you click enter in 9.0.124 it doesn’t dispatch a change event while in 10.0.0 it does. I’ve created a post on the Adobe forum to see if anyone is aware of this being a bug.

      For now, I’ve implemented a workaround in the code. I’ve checked a new SWC into the google code site, please give it a try and let me know if it resolves your issue.

      Thanks,
      Hillel

      • Ján Regeš Says:

        Hillel, thank you for your flash-fast response!

        Your workaround is working perfectly, good job!

        Btw, i have one idea/feature request :-)

        We use your AutoComplete component for thousands of items, but also for 20 items. It would be usefull, if we could set a flag, for example “comboBoxMode = true”. This feature will show down-arrow on right side and when you click on arrow, it display the entire menu.

        What do you think about it? This feature is beyond the basic AutoComplete functionality, but it would be usefull.

        Thank you!

      • Kamela Says:

        Hi Hillel!

        I have just tried your component today. I’ve checked at least 5 autocomplete combobox, and spent 20 hours with bug-fixing, without success.
        So, I downloaded your code, and found the issue, mentioned before. Thanks for the fast fix, it works for me too, and helped me a lot!

  2. Ján Regeš Says:

    Hi Hillel, again me :-)

    When i use “prompt” property and prompt is displayed, user must click into textinput two-times for focus it.
    This is user-unfriendly and inconsistent with functionality without the use of prompt feature.

    Thank you!

    • Hillel Says:

      Ján,

      I agree, having to click twice to focus is unacceptable. The challenge is I’m unable to replicate the issue. Does it work correctly for you when you try it in the demo?

      I’m planning on adding a comboBox button in the future, but for now you could do something like this (note, there was a slight issue with the dropDown when using this approach so I checked in a new SWC to resolve it).

      <?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"] );
      
      			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 icon="@Embed(source='/com/hillelcoren/assets/icons/down.png')" click="handleButtonClick()"/>
      		</components:inlineButton>
      	</components:AdvancedAutoComplete>
      
      </mx:Application>
      
      • Ján Regeš Says:

        This is fully sufficient!

        Btw, problem with focusing is only in one specific form in our large application.
        For imagine:

        ShellApplication / Module / FormWindow (popup) / Box / TabNavigator / Form / FormItem / HBox / AutoComplete / mainGridRow / mainGridItem / flowBox.textInput

        Unfortunately, it is not easy to replicate this issue in the sample application :-(

        FYI, when i added calling “callLater(setFocus);” to end of method-body hidePrompt() in PromptTextInput, it fixed this issue. It’s stupid solution, but works and unfortunately, i don’t have a time for analyzing the cause of this problem :-(

  3. Manna Says:

    Hi Hillel,

    Is it possible to quick edit the selected item?For example my data provider contain three record like “value1″,”value2″,”value3″.Now by mistake you select “value2″ instead of “value1″.
    Now I want to edit the “value2″ in selected item means
    I want to select “value1″ by replacing “2″ with “1″ from “value2″ and validate it.
    In the current scenario is it possible to accomplish this task.
    Please help.If you are not able to understand my question please let me know.

    Regards,
    Manna

    • Hillel Says:

      Manna,

      It’s a bit of a hack but give this a try and let me know what you think….

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application
      	xmlns:mx="http://www.adobe.com/2006/mxml"
      	xmlns:components="com.hillelcoren.components.*"
      	initialize="init()">
      
      	<mx:Script>
      		<![CDATA[
      			import mx.events.CollectionEventKind;
      			import mx.events.CollectionEvent;
      			import mx.collections.ArrayCollection;
      
      			[Bindable]
      			private var _data:ArrayCollection = new ArrayCollection( ["one","two","three"] );
      
      			private function init():void
      			{
      				autoComplete.selectedItems.addEventListener( CollectionEvent.COLLECTION_CHANGE, handleSelectedItemsChange );
      			}
      
      			private function handleSelectedItemsChange( event:CollectionEvent ):void
      			{
      				if (event.kind == CollectionEventKind.REMOVE)
      				{
      					var item:Object = event.items[0];
      					var str:String = autoComplete.labelFunction( item );
      					str = str.substring( 0, str.length - 1 );
      
      					// need to let the component clean out the old value
      					callLater( resetValue, [str] );
      				}
      			}
      
      			private function resetValue( str:String ):void
      			{
      				autoComplete.searchText = str;
      				autoComplete.textInput.textInput.setSelection( str.length, str.length );
      				autoComplete.textInput.setFocus();
      				autoComplete.search();
      			}
      
      		]]>
      	</mx:Script>
      
      	<components:AutoComplete id="autoComplete" dataProvider="{ _data }"/>
      
      </mx:Application>
      
    • Hillel Says:

      Manna,

      One other quick point: you’re may want to set backspaceAction=”remove” in the AutoComplete component. This way you’ll go right into edit mode when clicking the backspace.

  4. Manna Says:

    Hi Hillel,

    Thanks a lot & thanks for your awesome reply.I am going to implement your logic.

    Regards,
    Manna

  5. Manna Says:

    Hi Hillel,

    Thanks hillel.Everything is working fine except one small issue.After clicking on remove icon
    then selected item comes in edit mode.
    Because if we click the remove icon then also handleSelectedItemsChange fuction is getting called.

    Could you please tell us how can I stop to call
    handleSelectedItemsChange function when you click in remove icon.

    Regards,
    Manna

    • Hillel Says:

      Manna,

      This is why hacks suck: they never work quite right and the little issues the pop up just require mode bad code to fix. That being said, here’s a possible workaround…

      			private var _lastKeyPressed:uint;
      
      			private function init():void
      			{
      				autoComplete.addEventListener( KeyboardEvent.KEY_DOWN, handleKeyDown, false, 100 );
      				autoComplete.selectedItems.addEventListener( CollectionEvent.COLLECTION_CHANGE, handleSelectedItemsChange );
      			}
      
      			private function handleKeyDown( event:KeyboardEvent ):void
      			{
      				_lastKeyPressed = event.keyCode;
      			}
      
      			private function handleSelectedItemsChange( event:CollectionEvent ):void
      			{
      				if (event.kind == CollectionEventKind.REMOVE && _lastKeyPressed == Keyboard.BACKSPACE)
      				{
      					var item:Object = event.items[0];
      					var str:String = autoComplete.labelFunction( item );
      					str = str.substring( 0, str.length - 1 );
      
      					// need to let the component clean out the old value
      					callLater( resetValue, [str] );
      				}
      			}
      

      Add a private variable called _lastKeyPressed and store it when the user presses a key. Note, the priority is set higher b/c we need to catch it before the AutoComplete does. Then in the handleSelectedItemsChange add a check that _lastKeyPressed equals Keyboard.BACKSPACE.

  6. kfhwang Says:

    Hi Hillel,

    Can I use Clipboard to paste the copied string into AutoComplete and then showDropDown()?

    I use the following code:
    var copyStr:String=Clipboard.generalClipboard.getData(ClipboardFormats.TEXT_FORMAT) as String;
    AC.searchText = copyStr;
    AC.showDropDown();

    However, the dropdown list has no filter by the searchText;

    Thank you for your responding!

    BR,
    KFHwang

  7. kfhwang Says:

    Hillel, thank you very much!
    It works, but unnecessary to call AC.showDropDown().

    Thanks again!

    BR,
    Kfhwang

  8. Pier Says:

    Hi Hillel,

    got a question concerning the dropdownwidth. I’ve noticed that the drop down list’s width, when not set explicitly, is equal to the input’s width, regardless of the width of the dataprovider’s items’ width. However, specification of the combobox’s property is that it is equal to the max value between 100 and the largest width of the dataprovider’s items.
    did i miss something or is there a bug?

    • Hillel Says:

      Pier,

      I’m sorry, I’m not following. Where did you get the 100 value from?

      Essentially you have two options: by default it’ll just match the input’s width or you can specify a width in which case the dropDown will just match the width (regardless of the width of the items).

  9. Pier Says:

    sorry, the 100 comes from here: http://livedocs.adobe.com/flex/3/langref/mx/controls/ComboBox.html#dropdownWidth

    i understand the two options but what i don’t understand is that, according to Adobe’s documentation, if you don’t specify a width, it should take the width of the longest item. Obviously, that’s not working so i’m thinking about modifying your component to implement that functionnality. i’ve already found a few examples in the flex community of components doing so (eg: http://ifeedme.com/blog/?p=19)

    • Hillel Says:

      Pier,

      I follow you now, the AutoComplete component doesn’t extend from the ComboBox class (so it doesn’t implement this behavior). If you decide to implement this feature let me know if you need any help getting it working.

      Best,
      Hillel

      • Pier Says:

        My bad! i thought it was an editable Combobox type of thing. Well in that case, i’ll go ahead and make the modifications myself.
        Thanx for the info

  10. Ryan Says:

    In the examples, I see the “facebook style” has small “x’s” to delete items – but I can’t figure out how to get the “facebook style” to have those delete X’s when I’m using it with an AdvancedAutoComplete.

    I’m probably missing something – but is there some property I need to set?

  11. Ján Regeš Says:

    Hi Hillel.

    I found a bug in match highlighting. When i wrote “pa”, it highlight also “bo”, “br”, etc..

    Wrong and correct example with my fix is here:
    http://misc.drom.sk/images/others/autocomplete-highlight-bug-report.png

    I modified your StringUtil.as, method highlightMatch:

    // solution by Jan Reges, 2009-07-17
    var searchStrPattern:String = (“(“+searchStr+”)”);
    var returnStr:String = string.replace( new RegExp(searchStrPattern, ‘igm’), “$1” );

    /*
    var returnStr:String = string.substring( 0, matchPos );
    returnStr += “” + string.substr( matchPos, searchStr.length) + ““;
    returnStr += string.substr( matchPos + searchStr.length, string.length ) + ” “;
    */

    return returnStr;

    • Hillel Says:

      Ján

      Very nice!! I actually wanted to code it this way initially but had trouble getting it working.

      Thanks very much, I’ll include your change in the next release.

      Best,
      Hillel

  12. AutoComplete « Mjcprasad’s Blog Says:

    [...] 1.0 released on July 3rd, 2009 [...]

  13. Mike Orth Says:

    Great component, Hillel. In the case where the item’s labelField value is null, it will throw a RTE. One way is to fix is to always have a custom labelFunction to account for it. Or, in AutoComplete.mxml add this to the function “defaultDropDownLabelFunction”

    if (string == null)
    return “”;

    Cheers.
    Mike

  14. Matt Says:

    Hi Hillel,

    Thanks and great job on creating such an excellent component. I am working on an application that uses the AutoComplete and I am adding the ability to display the full dataProvider on FlowBox focus. When I have a working version, would you like me to post it up here for your approval?

    Ideally I would like to view the latest version of the source, but the google code site is currently displaying a “Forbidden” message when I access it. Do I require an account to use it?

    Many thanks,

    Matt

    • Hillel Says:

      Matt,

      Thanks, happy you like it :D

      Yeah, I’d love to see what you’re working. Maybe you could post a link to an example.

      I’ve just fixed the issue with the google code site, you should now be able to access it.

      Best,
      Hillel

  15. demo Says:

    Hi its is very nice components
    but i having a problem how can i set the global xy to local xy when i am creating its default starting from x=0, y=0, when you put any text also there is another problem seleted item appears with a button how can i disable that anyway , i am using Flex 4 , everything is fine except above those lines..

    thanks

    • Hillel Says:

      Demo,

      I’m sorry, I’m not sure I understand your global/local issue. You should be able to control how it looks by setting the selectedItemStyleName property.

  16. Manna Says:

    Hi Hillel,
    Is it possible to select multiple record with ctrl or shift key.As I know my autocomplete component availble for multiple selection. So is it possible to select mutiple records using only mouse click & after selecting all records user click the select option to dispatch the selected records.
    Please give some idea whether is it possible or not.
    Anticipating to get ur feedback soon.
    Regards,
    Manna

  17. Manna Says:

    Hi Hillel,
    Sorry I have made one mistake in my previous mail.Is it possible to select multiple record with out ctrl or shift key in datagrid.As I know my autocomplete component availble for multiple selection. So is it possible to select mutiple records using only mouse click & after selecting all records user click the select option to dispatch the selected records.
    Please give some idea whether is it possible or not.
    Anticipating to get ur feedback soon.
    Regards,
    Manna

    • Hillel Says:

      Manna,

      I’m sorry, the component doesn’t currently support that feature. If you’d like to implement it I’d be happy to help.

  18. Manna Says:

    Hi Hillel,

    Thanks for your reply.Yes I want to implement this feature in this component.Could you please guide me with some link or some hints.

    Regards,
    Manna

    • Hillel Says:

      Manna,

      Currently the buttons have the toggle property set to true. You’ll need to set this to false and then manually track which buttons are selected.

  19. Toton Says:

    Hello hillel,

    For the case of multiple selection,can we increase the height of flowbox(textinput) dynamically upto certain length.

    Any help will be appriciated.

    Regards,
    Toton

  20. David Cardinal Says:

    Hi–Your AdvancedAutoComplete component seems like just the solution we need compared to the buggy & not quite supported Adobe version.

    However, it seems to be quit a bit bigger and more importantly when we build a Flex application with it the result is very large. Are we missing something (we’re experienced programmers, but very new to Flex & Flash) about how to correctly use the SWC or build the SWF? We’re seeing sizes close to 1MB even for fairly small applications.

    Thanks!–David Cardinal

  21. Fayad Says:

    Hi,
    Great component thanks.
    I’m pre loading some data in a component using the addItem function.

    then, when the user tries to add some new records within the component (multiple selection) it doesn’t grey out (lock) the already pre loaded records.
    any ideas how I can lock the pre loaded records so the user can’t select them again and we won’t have duplicates.

    Thanks.
    Fayad

  22. Toton Says:

    Hi Hillel,
    I want to display the dropdownitem renderer as treeview mode.

    For examle my dataprovider contain like below format

    Animal
    Mammal
    cat
    dog
    Insect
    Ant

    Now user type “cat” in textinput.It will display like below

    Animal
    Mammal
    cat(Highlighted)
    dog
    Insect(Collapse mode)

    Now if user select Show all. It will display whole structure.

    Animal
    Mammal(Collapse mode)
    Insect(Collapse mode)

    If any thing is selected then that will be diplayed in greayed color
    (ex: cat & ant selected by the user)

    Animal
    Mammal
    cat(greayed color)
    dog
    Insect
    Ant(greayed color)

    [Note :There will be only one root parent for all child.(Ex:-Animal here)]

    Actually already I spend a lot of time but not find any good solution . Could you please help me with some hints. How can I modify your component to achieve the above requirement.

    Anticipating to get your feedback soon.

    Thank you for your kind assistance.

    Please help.

    Regards,
    Toton

    • Hillel Says:

      Toton,

      I’m sorry, I don’t believe this will be easy to accomplish. The item renderer is used to display a single item but in your case you need a single renderer (the tree) to display all of the items.

  23. Toton Says:

    Hi Hillel/All,

    Thanks for your reply. Can any of you come out with
    some idea, how can I accomplish the above functionality. It would be great if any of u can provide some guideline/link etc..

    If any of u think it is not possible to accomplish this please tell me the reason so that I can tell to my boss.

    If is there any other possible solution to achieve the simlar kind of functionality then I can design my own component but before to do that I want all of your suggestion how can I design this component.

    If you want to give me the suggestion u can mail me home4toto@gmail.com.

    Thank you for your kind assistance.

    Regards,
    Toton

  24. Murali Says:

    Hi Hillel,

    No wonder people are showering praises on you. This is one of the most comprehensive user extensions I have ever seen and I am not talking just about flex!

    I had some 3 or 4 small issues that your extension was not providing. But most of them were already encountered by other users and was explained in detail in the comments section. Thanks again!

    • Hillel Says:

      Murali,

      Thanks so much, that’s really nice of you to say :)

      Let me know if you run into any other issues.

      Best,
      Hillel

  25. Jamie Badman Says:

    Fixed the problem. Issue was I’m using ‘import artwork’ to skin my app. When you import artwork, it also generates a css file too. Just deleting the entry in that for ‘textInput’ fixes the problem.

    Cheers,

    Jamie.

  26. Vee Says:

    Dear Hillel,

    I reply here bcos of your kind pointing me a hint and I already successfully solve the problem. I’d like to thankyou for your time replied. I’m so much appreciated. I’d like to put the code here to whoever got the same issue I faced before,just in case you found it useful :)

    Here’s a complete “some way” for creating an autocomplete without button style within the search textinput(just the same as yahoo, google autocomplete)

    Thanks a ton again!! : )

  27. Vee Says:

    Well, it seems I have no permission to put the code in here.
    Mail to me if you need it :)

    • Hillel Says:

      Vee,

      I’m curious to see how you implemented it (I get that request a lot). If you could email me the changes that’d be great.

      Thanks,
      Hillel

      • SG Says:

        Hi Hillel,
        I need source code for autocomplete component without button style as Vee said. I try to set selectedItemStyleName to none but still got button style.
        Thx!

  28. Manna Says:

    Hi Hillel,

    Presently I am facing a big problem & it would be great if you provide some help on this.

    Problems like below:

    Presently my dataprovider can contain >100K records.

    So actually what I want, to use two seperate data provider one for dropdownItemRender (Which contain only few important data) means every time when you use Autocomplete.textinput option it will use this dataprovider.
    Another dataprovider for browser option which can contain all data.(Means here you can search all your data among 100k records & select that records).

    To solve this issue intially I thought :
    1)Assign the dataprovider for dropdownItemrender in
    handleKeyDown event
    2)Again reassign the dataprovider for browser option on handleItemClick function and remove this data from dataprovider when you are closing the browser option.

    But I think there should be a different way to implement this.If is there any different option please suggest me with that.

    Thank you for your kind assistance.

    Regards,
    Manna

  29. Angeline Says:

    Hi Hillel,
    Where is the link for the simple auto complete box without all the extra features?

    • Hillel Says:

      Angeline,

      There are two components: the AutoComplete and the AdvancedAutoComplete. They are both in the same SWC (and are therefore both in the same download).

      Let me know if this is unclear

  30. Guy Djemal Says:

    Hi Hillel,

    I need the ability to decide the disable color for the AutoComplete, my usage also includes disabling just the SelectedItem so even better if I could also specify a color for this too.

    I’m fresh out of ideas how to get this working without modify the code, any recommendations?

    Thanks,
    Guy.

    • Hillel Says:

      Guy,

      The ColorDemo provides a good example of how to do this (the source is in the examples folder). It uses the ColorItemRenderer.mxml file to control the color of the text based on whether or not the item has been selected.

      Let me know if you have any trouble getting this working

      • Guy Djemal Says:

        Hi Hillel,

        I actually meant the colors after the item has been selected and is displayed in the AutoComplete box, when you disable the AutoComplete it switches to a very light shade of gray. I’ve tried experimenting with the CustomSkin example to no avail.

        Guy.

  31. ёклмн Says:

    Почитал, порадовало :) А может и правда всегда думать исключительно о хорошем, а все плохое переворачивать?

  32. Guy Djemal Says:

    Hi Hillel,

    I’ve been having some problems with the sizing of PromptTextInput being set to a neglible value if an AutoComplete component is created for a hidden container. The consequence of this is that typed text is then not echoed to the screen.

    A solution that seems to work is to set the percentWidth of the PromptTextInput to 100% during the updateDisplayList() method in the FlowBox, specifically as below:

    if (child is PromptTextInput) {
    if (child.width + sidePadding > width){
    child.width = width – sidePadding;
    }
    // New line below
    child.percentWidth = 100;
    }

    Guy.

  33. Guy Djemal Says:

    Hi Hillel,

    I think my previous comment may have been missed but is quite a significant issue for my usage of the tool so worth repeating.

    BTW are you thinking of doing a new release soon to incorporate the various fixes?

    —-

    I’ve been having some problems with the sizing of PromptTextInput being set to a neglible value if an AutoComplete component is created for a hidden container. The consequence of this is that typed text is then not echoed to the screen.

    A solution that seems to work is to set the percentWidth of the PromptTextInput to 100% during the updateDisplayList() method in the FlowBox, specifically as below:

    if (child is PromptTextInput) {
    if (child.width + sidePadding > width){
    child.width = width – sidePadding;
    }
    // New code below
    child.percentWidth = 100;
    }

    Guy

  34. VawAverenaw Says:

    А мне блог понравился

  35. Hillel Says:

    Guy,

    Ahh… gotcha, that’s a bit trickier. The CustomSkin applies the same skin to all of the selected items. You could try looping through the flowBox’s children, these will (except for the last child) be SelectedItems. You could then manually set the styleName property of the button component to a skin.

  36. Hillel Says:

    SG,

    The component currently doesn’t support this. I seem to be getting this request a lot lately, I’m going to consider implementing it in a future release.

    For now… here’s a comment which discusses a hack implementation of this sort of feature.
    http://hillelcoren.com/2009/07/03/flex-autocomplete-version-1-0/#comment-1054

Leave a Reply