Flex AutoComplete: Version 0.98.2

Note: The interface for the component has been changed a fair bit in this version. If you’re upgrading, please refer to this post to determine the changes you’ll need to make.

Latest version

I’ve found that I very often need to use the component as a basic autocomplete combobox, without all the extra jazz. To simplify things, I’ve split the component into two classes: AutoComplete and AdvancedAutoComplete.

I’ve moved a lot of the extra features (such as browsing and ordering) to the AdvancedAutoComplete component. The demo and documentation provide breakdowns of which features are where.

The catch with this approach is if you need one of the features from the advanced component you have to take them all. It looks like Gumbo will implement changes to the component framework which will enable implementing a better solution. I’m planning to rework the component once it’s officially released.

Additionally, I’ve changed the names of a number of properties to better follow the conventions used throughout the Flex framework.

Old Name New Name
isMultiSelect allowMultipleSelection
multiSelectLayout selectionLayout
isStrict allowNewValues (note: logic is reversed)
areNewItemsEditable  allowEditingNewValues
isBrowseable showBrowseButton
isOrderable showOrderButtons
styleName selectedItemStyleName (note: now a style)

Here’s what’s new…

  • Created inlineButton feature: You can now set a button to appear at the end of the combobox.
  • Added Actions Menu: I’ve used the new inlineButton feature to implement an actions menu in the AdvancedAutoComplete component. The feature is enabled by setting a value for the actionsMenuDataProvider property. I’ve added the option to the advanced tab in the demo.
  • Support for skins: The selected items have been changed to buttons which has enabled me to rework the MacMail and Facebook styles as skins. I’ve created a CustomSkin example application which demonstrates how to create your own skin. If you end up creating any nice skins please send them my way. One note here, if you’re using the source you’ll need to include the defaults.css file in your app.
  • Added autoSelectEnabled property: One of the most common questions posted is how to prevent the component from automatically selecting a match. You used to have to create a function which always returned false for the isEqualFunction property. You can now simply set autoSelectEnabled to false. If you’d like to implement a custom function you can set it in the autoSelectFunction property.
  • Bug fixes and tweaks: As always, I’ve gone through all of the comments and fixed any bugs which people have spotted.

Lastly, I wanted to thank Demetri for convincing me to create it, creating the icons and guiding the UI decisions along the way and Tarak for allowing me to share it (and introducing me to Flex). Thanks guys!

275 thoughts on “Flex AutoComplete: Version 0.98.2”

  1. Thanks for the component. I’ve just started using it today and after a few hours I noticed you’ve release the next version 😉

    I’m using the component as a search input with some kind of auto suggest with the use of auto complete. I use the CHANGE event to trigger the actual search. I needed to add dispatching of CHANGE event in two places:
    – handleItemRemove so that it is dispatched when user clicks the remove icon
    – handleFocusOut as the so far entered text is used to form a selected item

    1. Piotr,

      These two events should cover your cases
      autoComplete.addEventListener( Event.CHANGE, handleChange );
      autoComplete.addEventListener( FocusEvent.FOCUS_OUT, handleFocusOut );

      The change event is fired when items are added or removed, and although the component doesn’t have the meta-data for the focusOut event it does work if you set it using addEventListener.

      I hope to have a setting to control whether or not to hide the inline button in the next version.

      1. Thanks for your reply. I do understand your solution but I’m not sure that this is the Right Way To Do That 😉 Let’s put it this way: I hoped to get notified by Event.CHANGE on any changes to the input, but this doesn’t currently cover two cases:
        – the user clicks the remove icon on an element,
        – the user starts to write and then hits TAB button

        I’ve also noticed one small, a bit annoying, behavior. If I allow new values and the user starts to type, e.g. ‘compl’ and there is already a value of ‘completed’ in dataProvider, there is no way for the user to accept ‘compl’ as new value.

        But besides these small bugs, the component is GREAT! 🙂

      2. Piotr,

        Thanks for restating your issue, I gotcha now. Yes, that’s definitely a bug. I’ve just checked in a new SWC into the google code site.


        As for your second point. The user has two options, they can either click ESC (to close the dropDown) and then click ENTER or they can enter a comma to select the value. Let me know if you have any suggestions to improve this behavior.

        As for your second point. The user can click ESC (to close the dropDown) and then click ENTER. Let me know if you have any suggestions to improve this behavior.

      3. ESC would be the solution for me… if I didn’t use ESC already to close the window in which I use AutoComplete. The problem I see is that KeyboardEvent in Flex cannot be stopped.

        But in general, I think that ESC is OK for this.

        Therefore, I modified the code a bit for my own purposes. Now, when the user types ‘compl’ (and there’s ‘completed’ in dataProvider) followed by comma, his input (‘compl’) is used instead of the element from dataProvider.

        So this way focusing out, using TAB or ENTER accepts the first element from the drop down menu but comma accepts the input that was typed so far regardless of the drop down menu.

  2. I use the autocomplete-control in an AdvancedDataGrid. It works outstanding!
    Now I want to save data remotely after the user edits the control.
    I can’t find an event generated when the user stops editing the autocomplete.
    I can’t use the change-event because it fires when the control has already data in it when the user starts editing.
    Any ideas?
    Thank you

  3. I was trying to use the component as follows:

    hc:AutoComplete id=”udrAC” allowNewValues=”true” allowMultipleSelection=”false” dataProvider=”udrs”/

    I am facing some problems with the new values. When the user enters a new value, I expected ‘selectedItem’ to be null and ‘text’ to contain the new value. However, I find that text is blank and selectedItem is now a string instead of an Object from the dataProvider or null.

    Is this correct behavior?

    1. Maneesh,

      Thanks for the support, you’re feedback has been incredibly helpful getting the latest version ready for release.

      The behavior is actually correct. I’ve needed to complicate the API of the component to support multiple selection. For example, I’m not a big fan of the searchText field but it’s needed as the text field is used for the other items when using it as a multiple select box. We could change the meanings of the properties depending on whether allowMultipleSelection is enabled (ie, if it’s single select then you could just use the text property rather than searchText) but I believe that would make the API of the component less consistent.

  4. Just a small note: it would be great, if one could set the inline button to be visible permanently.

  5. It would also be nice to make dataProvider in Browser actually bind to the source dataProvider so that the list in Browser is refresher whenever the source dataProvider changes. As far as I can see, _list.dataProvider is currently assigned once during creation.

    1. Piotr,

      It should already work that way, although the dataProvider is assigned during creation we reassign the dataProvider if it changes on line 287 of AutoComplete.mxml.

      1. Ah, yeah you’re probably talking about changing the contents of dataProvider and this probably works. What I’m doing is I’m changing the dataProvider completely, i.e. reassigning the dataProvider of AdvancedAutoComplete object.

        The first problem I see is that you use

        [Bindable] meta tag for _dataProvider (in AutoComplete and in Browser) but incorrectly use it before variable definition, e,g:

        [Bindable]
        private var _dataProvider:ArrayCollection;

        whereas you should use if before set function. See http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_8.html
        point 3. This makes Flex correctly dispatch PropertyChangeEvent for you.

        Then, I had to use BindingUtils.setProperty in AdvancedAutocomplete and Browser to use Flex binding machanism instead of assigning the dataProvider just once. I added

        Browser.mxml:88:
        BindingUtils.bindProperty(_list, “dataProvider”, this, “dataProvider”);

        AdvancedAutoComplete:242:
        BindingUtils.bindProperty(_browser, “dataProvider”, this, “dataProvider”);

        ah, and there are some get dataProvider functions missing.

      2. Piotr,

        To begin with thanks for posting your solution, the changes you’ve made have clearly solved your problem so I’d very much like to figure out what’s going on here.

        I’m sorry, I made a mistake in my last reply. The code I referred to updates the dataProvider for the dropDown. The dataProvider for the browser is assigned each time the browser is displayed. The only time (I think) there would be an issue is if the dataProvider is changed while the browser is visible (is that your case?).

        My understanding is that the [Bindable] tag can be placed either before the variable of the function. The only difference is that if it placed before the variable, the propertyChange event is fired automatically. As per the link you sent me, “In this case (placing it before the function), you are responsible for generating and dispatching the event, typically in the setter method, and Flex does not check to see if the old value and the new value are different.”.

        Thanks for your patience in getting to the bottom of this

      3. Exactly – my case is that dataProvider is changed completely once the Browse has been displayed (showBrowser()). I solved the issue with the steps I described before.

        As for the [Bindable] meta tag:

        [Bindable] can be placed before the variable (point 2). In this case you don’t have your own set/get function.

        But if you use set/get function (and therefore the name of the variable != the name of the function) you put this metatag before the set or get function. If you stick to default event name, you do not have to dispatch it manually. This is the case in your code – you have set/get functions but you incorrectly put [Bindable] before variable when you should actually use this metatag before set or get function.

        If you use [Bindable(event=”myEvent”)] you are then responsible for dispatching it (second part of point 3 from Adobe manual).

        There’s a good presentation explaining what is actually happening when you use data binding: http://www.onflex.org/ted/2008/08/diving-in-data-binding-waters-with.php

        Now, back to my case. Yes, I was changing dataProvider once the browser has been shown (showBrowser()). I kind of fixed it but I’m now not sure whether I should actually stick to this solution. The problem is that I may have some data in dataProvider, show the browser and then, a bit later, update (complete change) the dataProvider. Now, if the user has already selected an item from the list, changing dataProvider makes it lose the selection which is leads to a kind of bad user experience 🙂

  6. Hi Hillel,

    Brilliant work providing us with such a rich component. Certainly something that I have been looking for. I have recently (last couple of days) included Version 0.98.2 in my project. My client wants something to work such as the email selector in GMail (user chooses a contact from the drop down and a semi-colon is automatically added to the end.)

    I used selectedItemStyleName=”underline” which provided me with almost the same functionality as GMail except a comma is used instaed of a semi-colon. The real problem arose when I tried to delete a selected item displayed in the AutoComplete text box :
    —————————————————
    RangeError: Error #2006: Index out of range
    at flash.text::TextField/setTextFormat()
    at mx.core::UITextField/setTextFormat()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UITextField.as:1445]
    at com.hillelcoren.components.autoComplete.classes::IconButton/updateDisplayList()[/Users/hillel/Code/flex-autocomplete/src/com/hillelcoren/components/autoComplete/classes/IconButton.mxml:109]
    at mx.core::UIComponent/validateDisplayList()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:6351]
    at mx.managers::LayoutManager/validateDisplayList()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:622]
    at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:695]
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8628]
    at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8568]
    —————————————————

    Mxml implementation:

    ———————————————–
    imports:
    import com.hillelcoren.components.*;
    import com.hillelcoren.components.autoComplete.classes.*;
    import com.hillelcoren.components.AutoComplete;
    ———————————————–

    I’d really appreciate it if you could help me with this Hillel.

    Also, would it be easy for me to change the comma to a semi-colon?

    Andy

    1. Andy,

      I’d be happy to help you with this. Could you please repost the MXML (you need to replace all angle brackes with ampersand lt; for less thans and gt; for greater thans)

      1. Thanks for your speedy response Hillel. Here’s the mxml

        <hc:AutoComplete
        id=”acGuestEmail”
        dataProvider=”{ DG_Guests }”
        labelField=”GuestEmail”
        matchType=”beginning”
        prompt=”Select a friend”
        allowNewValues =”true”
        allowMultipleSelection=”true”
        allowDuplicates=”false”
        allowEditingNewValues=”true”
        dropDownItemRenderer=”{ dropDownItemRenderer }”
        x=”143″ y=”14″
        enableClearIcon=”false”
        fontFamily=”Century Gothic”
        fontStyle=”italic”
        fontSize=”12″
        color=”#000000″
        borderStyle=”none”
        cornerRadius=”10″
        paddingLeft=”3″
        paddingRight=”3″
        height=”18″
        width=”310″
        backgroundAlpha=”0.0″ selectedItemStyleName=”underline”
        change=”handleAutoCompleteChange()” showRemoveIcon=”false” />

      2. Andy,

        I think I may have figured it out. It looks like there’s a failure case if the labelField (or labelFunction) returns a blank string. I’ve checked in a new SWC into the google code site which should eliminate the bug. But I’d recommend you check your dataset to see if there are any objects which would return a blank label (even if this error is resolved you probably wouldn’t want that).

        Let me know how this turns out…

      3. Andy,

        Wait… I’m missing something. I’m not sure that this is the issue here as it wouldn’t explain why you get the error when you delete an item, something else must be going on. Does this error occur when you delete an item selected from the dataProvider as well as when you delete a newly added item.

      4. Hi Hillel,

        That would explain it but (and sorry about the but) I’m not deleting anything from the dataProvider. I downloaded the latest swc build from code.google (revision 111) and I’m still having the error. It did seem to almost work at one stage – added 5 items and managed to delete 4 (I couldn’t remove anything yesterday without having the runtime error).

        The other tries were pretty much unsuccessful, I say pretty much because there were a couple of times when I managed to delete items, this seemed to be when I added a new entry in the autocomplete text box (after selecting items from the drop down) or depending where the cursor was positioned. It was really hard to reproduce successful deletes so I can’t say for certain when the problem arises, but the problem occurs 99.9 % of the time and I’ve never managed to remove the first item from the selected items.

        This is frustrating because this baby almost works and I can imagine how frustrating it may be for you to diagnose the problem.

        Please let me know if you require further info. to assist you.

        Cheers for so far.

        Andy

      5. Andy,

        The best thing for me would be if you could create a small sample application which demonstrates your problem, maybe there’s something specific with your dataset which is causing the issue.

        Let me know if this won’t be possible and we’ll try to come up with something else.

        Thanks for working through the issue with me,
        Hillel

      6. Hey Hillel I’ve figured it out. You’ll be happy to know that it’s nothing to do with your code but what seems to be a wacky flex character bug.

        If I specify to use fontFamily=”Century Gothic” in the autocomplete mxml tag and have a combination of characters in a collection item then this will create the runtime error, eg having the text: andy@mymail.tffff. Most of the emails in my collection had a .fr extension, the “f” with certain other character combinations resulted to failures.

        The simple solution (and I do hope it will work for all situations) was to change Century Gothic to Arial. So far all is going well.

        Thanks again for your willing assistance Hillel.

        Regarding the comma separators, can they be easily replaced with semi-colons?

      7. Andy,

        I’m very happy to hear that you were able to figure it out, thanks for letting me know what the issue was.

        I’ll add the ability to set the separator to my list for a future release. For now, I’d suggest using the source code and make the modification directly. Here are the places you’ll need to change it.

        AutoComplete.mxml – addItem()
        EditableItem.mxml – handleFocusOut()
        IconButton – commitProperties()

        Let me know if you need any help getting this working.

      8. Hillel,

        I am trying to remove “,” and use “;” so tried editing files as per above but couldnt succeed.

        Please help.

      9. Hillel,

        I am not getting error but when I try to search with comma, it selects the value.

      10. Gaurav,

        When you say “as per above”, I’m assuming you’re referring to the comment where I explain how to change the delimiter. The issue with the comma selecting the item is a different issue but as luck would have it I posted another comment explaining the changes you’d need to make to resolve this issue.

        http://hillelcoren.com/2009/05/11/flex-autocomplete-version-0-98-2/#comment-941

        Sorry you have to make so many changes. I would have thought that these were edge cases but I guess when enough people use a component the edge cases start happening more often.

    1. Joseph,

      Awesome, happy you found it. Let me know if you run into any issues, I’ll try to provide as much support as possible.

      Best,
      Hillel

  7. Hi Hillel,

    I have another question for you if that’s OK. I would like to limit the size of the text input control for whatever amount of data is added to it. At the moment the text control expands vertically. I would like to limit this in both directions.

    Can this be easily achieved or do I need to make changes to the source?

    Cheers Hillel,

    Andy

    PS Apologies if this message shows up twice – I couldn’t see my message for my first try.

    1. Andy,

      You can set the height of the FlowBox component…

      autoComplete.flowBox.height = 50;

      The catch with this approach is it looks like it doesn’t show the scroll bars. I’m heading out for the weekend and don’t have time to figure that out for you but if you don’t get it I’ll take a look at it tomorrow night.

      Best,
      Hillel

      1. Hi Hillel,

        I took at look at this last Friday. autoComplete.flowBox.height worked just right but yes there was a problem with the scrollbars displaying.

        I tried setting:

        autoComplete.flowBox.verticalScrollPolicy = “auto” and
        autoComplete.flowBox.textInput.verticalScrollPolicy = “auto”; but no luck.

        Sorry, looks like I will need your help with this one.

        Thanks Hillel,

        Andy

      2. Andy,

        This seems to work for me

        autoComplete.flowBox.height = 50;
        autoComplete.flowBox.verticalScrollPolicy = ScrollPolicy.AUTO;

        Please try using this in a test application to see if it works for you

  8. First of all, thanks a lot for this very useful component. Now I’m investigating whether I could use this component as a formula editor. Is it possible to mix in auto-completed values (variables in my case) with plain text (operators, braces and constants in my case)?

    1. Sébastien,

      If you set the “allowNewValues” property to true, it would allow the user to either select variables or enter operators. I’m not sure if I have a clear vision of what your attempting to accomplish though. If you could point me to an example online I might be able to provide additional help.

  9. Hillel,

    Is there a easy way to see if what the user typed in has any matches in the drop down. What I want to do is have a button that will only allow them to click if if they found a match. If the match wasn’t found the button is disabled

    btw great component

    1. Brett,

      How’s this…

      <components:AdvancedAutoComplete id=”autoComplete” dataProvider=”{ items }”/>
      <mx:Button label=”Click Me” enabled=”{ autoComplete.selectedItem != null }”/>

  10. Hello Hillel,

    I am very new to Flex programming and I’m trying to figure out if I can use your control to perform the following. I have a C# .Net web service (way more familiar with C#) that I’m calling from my Flex app, that does an Active Directory LDAP lookup based on the string provided returns a datatable filled with the cn and email results that contain a match to the string provided in the app. I would like to setup the contol to not make the call to the web service until after the user types at least 2 characters, then display the results in the drop down.

    How can I accomplish this?

    1. Jay,

      In the examples folder in the zip file there’s a file called DynamicData.mxml, it’s actually very close to what you’re describing. You’d just want to replace the timer with a call to the server. Please take a look at it and let me know if you need any help getting it to work for you.

      1. Hillel,

        This is a great component! Thanks for sharing.

        I have it working and returning values from the .Net web service I created. I had a few questions around how I can make it a better user experience in my app.

        Currently when a user starts to input text, after they have entered 2 characters, it will supply those first two characters to the web service to perform a lookup in Active Directory of all groups or users with those two characters in the name, and return the cn and email as results in a datatable. I then fill an ArrayCollection with the resulting rows of data in Flex. On the AutoComplete I have allowMultipleSelection=”true” , when the user selects a name from the first lookup, I would like to clear the results in the ArrayCollection and begin a new search, or if the user backspaces and starts a new search.
        The other thing I would really like the AutoComplete to do is temporarily disable the input field while the lookup to the webservice is taking place and re-enable after the results come back, but that might be asking a bit much of my limited Flex programming abilities.

      2. Jay,

        On your first point I’m sorry I’m not clear on what the question is, to clear the results you could call dataProvider.removeAll().

        For the second point you can set the “enabled” property to false when searching (and then true once the results are returned), but… I’d argue against that as it won’t be a very friendly UI. I think a better approach would be to display a spinning loading icon when searching the server. As an example, http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&loc=en_us&extid=1219018.

        I’ll add to my list for a future release to incorporate the loading spinner in the component directly.

  11. Hi, thanks for this amzing component.
    Just a little issue : it doesn’t seem to work when using it in a TitleWindow.

    1. Benoit,

      Hmm… there must be something else going on here. I use it all over the place in my application inside titlewindows. Would it be possible for you to provide me a sample application which demonstrates the problem?

      Thanks

  12. Hi Hillel,
    first of all, congrats on the new version as it has corrected the two bugs i had with it (validation styling and long labels displaying a graphical bug) 😀
    and the selected item skinning is grand too.
    I am however wondering, concerning the selected item display, if there is a possibility of not having the item displayed as an object. My client would seem to prefer having a simple String instead of the object mainly because the deleting of said selected item isn’t natural to him (i.e. having to press Backspace twice to delete object rather than having the Backspace button delete the letters one by one).
    So before i delve into the souce code and modify everything, i’d like to have your opinion on the matter.
    I’m guessing that the reason why you’ve implemented it that way is in the case of multiple selections.

    Cheers,
    Pier

    1. Pier,

      You can set the “backspaceAction” property to “remove” which will make it so you don’t need to click backspace twice.

      Hope that helps

  13. Hi Hillel,

    How can I change the style to “Underline” like in your demo ? When I use the 0.98.2 swc file I don’t find the property …

    Thx in advance and thanks a lot for your component

    1. Cedric,

      In version 0.98.2 the property for the style was changed from “styleName” to a style called “selectedItemStyleName”.

  14. Hi Hillel,

    A few more problems:

    1. Change your application’s default font size to 2. Then use a multi-select list builder. Buttons are no longer visible and there are scroll bars galore.

    2. In any autocomplete field, type a few characters so that the drop down shows. Then press tab. This will select the currently highlighted item in the drop down and move the cursor to the next form field. It is expected that there will be one change and one valuecommit event. But there are two valuecommit events. One when the item gets selected and one when the focus moves.

    3. Your component does not have focusin and focusout events.

    Thanks for all the help.

    1. Maneesh,

      Thanks for letting me know about the issues, I’ll spend some time tomorrow trying to resolved them.

    2. Maneesh,

      1. I wasn’t able to replicate your issue, would you be able to provide a sample app.
      2. The valueCommit event is used mainly for validation. What makes things tricky is the component is a combination of TextInput and ComboBox. The TextInput fires a ValueCommit event on focus out while the ComboBox fires it on change. With validation, if it’s a required field I want it to be validated if the user just enters then exits the field, but if they change it I need it to revalidate.
      3. The issue here is that the component inherits from Grid. The Grid class (along with it looks like all container class) have metadata which excludes the focusIn/Out events (along with others). Although they’re excluded they still work. For example:

      autoComplete.addEventListener( FocusEvent.FOCUS_IN, handleFocusIn );
      autoComplete.addEventListener( FocusEvent.FOCUS_OUT, handleFocusOut );

      1. Maneesh,

        Thanks for the clarification, I was wondering why you’d want the font so small 😉

        I’ve just checked in a fix for it.

        Thanks!!

  15. I’ve just stumbled across your Flex widget and it looks really nice. We’re interested in something very similar for an app we’re working on, but I was wondering about 2 things:

    1. Can you enable the ‘advanced view’ to have all elements show up in the list by default (before the user starts typing anything)?
    2. Can you add checkboxes inline on the list view to facilitate ‘multi-select’ functionality?

    We’re interested in a widget that mimics the functionality you find on sites like endless.com (http://www.endless.com/Mens-Shoes/b/241993011/ref=topnav_sd_mn_gw), where users are presented with a full list that is filtered by their text input.

    Thanks for the help.

    1. Nathan,

      For what you’re trying to accomplish I wouldn’t suggest using the AutoComplete component.

      It actually shouldn’t be too hard to create from scratch. I’d suggest starting with a list and using an ItemRenderer which contains a checkbox and a label. You’d then want to make clicking the item in the list add/remove it from the selectedItems property.

      Let me know if you need any help getting this working

      Best,
      Hillel

  16. Hi Hillel,

    Is it possible to display the actions menuItem icon(displayed on flowbox as inline button)all time.Please give some hint on this.

    Anticipating to get your kind reply soon.

    Best Regards,
    Sourav

    1. Sourav,

      I agree that the icon should be shown by default. I’ve changed it so that it starts visible but is hidden if the user clicks inside the component. You can get the latest version from the google code.

      Hopefully this works for you

      1. Why should the icon be hidden at all? Why can it not be visible all the time? If the problem is that it may interfere with the text, then you probably need to change the way it works. ComboBox and DateField are able to have permanent inlinebuttons without any problem.

      2. Maneesh,

        I agree. I had initially hidden the icon b/c there was a graphical quirk which I couldn’t figure which occurred when the component got taller (from adding items). It looks like other changes I’ve made have resolved that issue so we’re now able to always display the icon. I’ve just checked in a new version.

        Thanks for pointing it out, I think it’s a lot better this way.

  17. Hi Hillel,
    Thanks for your reply.
    I have some query.It would be great for me if you provide some hint on this –
    1)Is it possible to allow user to select multiple records only on Browse option and all the selected records filled in the input text of picklist separated by “;”
    2)Is it poosilble to disable the input text and allow user to select multiple records only from browse option.

    Regards,
    Sourav

    1. Sourav,

      1. Currently, the component doesn’t support specifying the delimiter (I hope to add this feature in a future release). For now, you can use the source code and change “,” to “;”. Here’s another comment I posted which specifies the locations where you’ll need to make changes. http://hillelcoren.com/2009/05/11/flex-autocomplete-version-0-98-2/#comment-673.

      2. Here’s one possible solution to enforcing that the user add items using the Browse option.

      autoComplete.flowBox.textInput.textInput.enabled = false;
      autoComplete.flowBox.textInput.textInput.setStyle( “backgroundDisabledColor”, “#FFFFFF” );

  18. Thanks for releasing another update. I notice a few bugs with my configuration.

    hc:AdvancedAutoComplete id=”packages”
    selectedItemStyleName=”{AutoComplete.STYLE_FACEBOOK}”
    showRemoveIcon=”true”
    showBrowseButton=”true”
    useListBuilder=”true”
    allowMultipleSelection=”true”
    allowDuplicates=”false”
    selectedItems=”{suggestedPackages}”
    labelField=”pkg”
    dataProvider=”{myPackages}”

    1. the change event is triggered when I hit the Browse button and then OK without changing any data

    2. the change event is not triggered when I click on the ‘X’ of the showRemoveIcon to delete an item even the data did get removed from the list

    3. if allowMultipleSelection=”false”, labelField=”pkg” will not longer work, all the fields in the object are shown

    1. tmv,

      Thanks for spotting these issues:

      1. I’ve just checked in a fix for this issue (please download the latest code/swc from the google code site).

      2. This has also been fixed in the latest code.

      3. When you say “all fields are shown”, where are you referring to?

      1. >When you say “all fields are shown”, where are you referring to?
        Let’s say my I have an object with attributes: name, color, size, etc. If the labelField=”name” then name should only be shown, but in this case color and size are also shown.

      2. I forgot to clarify that all attributes (name, color, size) are shown in the pop-up grid when you hit the Browse button.

      3. tmv,

        Gotcha… to fix that you’ll need to set the browserFields property. By default we show all the fields in the grid, this allows you to specify an array containing the fields to show.

  19. Hillel,

    Is it possible that when a user clicks and selects the first match they made by clicking and then be able to type over it for a new match…not sure if you can understand want I mean. Basically it would be like a textfield that when the users types something then goes back in to focus on the textfield it will highlight the whole word so the user can start typing again.

    1. Brett,

      Not sure I follow you entirely, but… when allowMultiple selection is disabled, if you focus the component and type it will remove the selected item. If you click and focus the item itself, only the backspace key is listened for.

  20. Great component, I am definitely going to get a lot of use out of it.

    I’m having one small issue.. When i adjust the defaults.css file so that the font is embedded, like so:

    AutoComplete
    {
    selected-item-style-name: macMail;
    fontFamily:Arial;
    fontSize:12;
    }
    ….
    @font-face
    {
    fontFamily: Arial;
    fontWeight: normal;
    fontStyle: normal;
    src: local(“Arial”);
    }

    .. the user is required to double click on the input field to begin typing. Am I doing something incorrectly?

    Thanks again for sharing this!
    jr

    1. jr,

      I”m sorry, I’m not able to reproduce your issue. Could you please try creating a test application which demonstrates your problem.

      Thanks

    2. jr,

      Also, it’s worth mentioning that the code you supplied generated errors for me (I’m on a mac?)

      I used the following code to make it work with embedded fonts

      AutoComplete
      {
      selected-item-style-name: macMail;
      fontFamily:ArialEmbedded;
      fontSize:12;
      }

      @font-face {
      src: local(“Arial”);
      fontFamily: ArialEmbedded;
      fontWeight: normal;
      }

      @font-face {
      src: local(“Arial”);
      fontFamily: ArialEmbedded;
      fontWeight: bold;
      }

    3. Great component Hillel.

      FWIW, I couldn’t get this to work with embedded fonts at all. I had to set font-family: null; in order to override a default Application setting for family.

      Setting things just as you describe above still resulted in the user having to click twice to get focus to type.

  21. Hillel,
    I ran across an issue where setting the .tabIndex on an AutoComplete instance would not propogate to the inner TextInput field, thus, tabbing over an AutoComplete component would not work (it would be skipped). I could hack the calling code to look something like:
    autoCompleteComp.flowBox.textInput.textInput.tabIndex = 4;

    Very verbose and prone to errors if the internal makeup of the component changes. I made the following changes to remedy this of which you may want to put into the source trunk:

    —- AutoComplete.mxml ——
    override public function set tabIndex(value:int):void {
    flowBox.textInput.textInput.tabIndex = value;
    }

    override public function get tabIndex():int {
    return flowBox.textInput.textInput.tabIndex;
    }

    —- Sample usage of this would be ——
    myDateField.tabIndex = 1;
    autoCompleteComp.tabIndex = 2;
    otherComponent.tabIndex = 3;
    …and so on….

    1. Ry,

      You rock, thanks! Yeah, that makes a lot of sense. I haven’t need to mess with the tab indexes myself but I could see that being a problem.

      Thanks for the fix

      1. Here are some more additions for enabling the PAGE_UP, PAGE_DOWN and DELETE key press:

        —- In AutoComplete.mxml ——
        /**** Added support for the PAGE_UP and PAGE_DOWN key to paginate the list ****/
        #Added at line 618
        else if (event.keyCode == Keyboard.PAGE_UP)
        {
        if (_dropDown.selectedIndex == 0)
        {
        _dropDown.selectedIndex = _dataProvider.length – 1;
        }
        else
        {
        _dropDown.selectedIndex -=
        _dropDown.selectedIndex – _dropDownRowCount _dataProvider.length – 1 ? _dataProvider.length – 1 : _dropDownRowCount;
        }

        _dropDown.scrollToIndex( _dropDown.selectedIndex );
        textInput.setCursorPosition( textInput.selectionBeginIndex );
        }

        /**** Added support for the DELETE key to remove the current selected element ****/
        Changed:
        if (event.keyCode == Keyboard.BACKSPACE)
        {
        if( index > 0 ) {
        _selectedItems.removeItemAt( index – 1 );
        dispatchEvent( new Event( Event.CHANGE ) );
        iComboItem( flowBox.getChildAt( index – 1 ) ).setTextFocus();
        }
        }
        to:
        if (event.keyCode == Keyboard.BACKSPACE || event.keyCode == Keyboard.DELETE)
        {
        if( index > 0 ) {
        _selectedItems.removeItemAt( index – 1 );
        dispatchEvent( new Event( Event.CHANGE ) );
        iComboItem( flowBox.getChildAt( index – 1 ) ).setTextFocus();
        }
        }

        Changed:
        if (_backspaceAction == AutoComplete.BACKSPACE_REMOVE)
        to:
        if (_backspaceAction == AutoComplete.BACKSPACE_REMOVE || event.keyCode == Keyboard.DELETE)

      2. Ry,

        Awesome, I just added you to the project. I’ve haven’t yet added your changes so if you could add them for me that’d be really helpful.

        Look forward to your contributions,
        Hillel

    2. Any way to set it up so it works in mxml? I’m getting errors because the flowbox doesn’t exist when those attributes are being set…

      ypeError: Error #1009: Cannot access a property or method of a null object reference.
      at com.hillelcoren.components::AutoComplete/set tabIndex()

      Also, I tried this with tabEnabled (even just setting tabEnabled = true in the nested textinput) to no avail. Any ideas why that wouldn’t work?

      1. Alex,

        You’d need to do something like the following… (note: this would be added to each of the classes in the hierarchy. ie, AutoComplete, FlowBox and PromptTextInput)

        override public function set tabIndex(value:int):void
        {
        _tabIndex = value;
        _tabIndexChanged = true;

        invalidateProperties();
        }

        override protected function commitProperties():void
        {
        super.commitProperties();

        if (_tabIndexChanged)
        {
        _tabIndexChanged = false;
        textInput.tabIndex = _tabIndex;
        }
        }

  22. Hi,
    Excellent component. I am in the process of switching from Yahoo’s autocomplete manager.

    1. I would like to have a style property to disable underlining items in the dropdown. Currently I have to use a dropdownItemRenderer with a label.

    2. Is it possible to use backspace to delete characters instead of the complete selected item. So if user has previously selected “Omini” and he wants to change to “Omega”. Backspace could be used to remove last 3 chars as in normal editing instead of clearing the contents of input control.

    3. There are some issues with space character. I will try to test more and report here.

    Thanks/

    1. Tahir,

      1. A simpler approach is to set the dropDownLabelFunction to a function which returns just the label. Something like:

      public function dropDownLabelFunction( item:Object ):String
      {
      return item.name;
      }

      2. Have you tried setting allowEditingNewValues to true.

      3. Look forward to hearing more specifics, thanks!

      1. Hillel,

        Thanks for the tip for #1.

        I tried #2 but it doesn’t many any difference. Let me recap.

        One of the basic requirement for this component is to be used instead of standard ComboBox. ComboBox is good but gives serious usability issues where dataprovider has more than 10-15 items.
        So AutoComplete should (IMHO) provide a strict mode where only values from the dataProvider are allowed.

        I wanted to switch from Yahoo’s Autocomplete manager because that has the same issue. I had to catch keyboard/mouse events to remove the text if it doesn’t exist in dataProvider.
        But you should have a look at the way AutoComplete manager handles editing. It leaves it as standard TextInput so you can edit the text just as you would any TextInput.

        3. If the text is selected in AutoComplete, pressing space character deletes it and inserts a space character in the Text. This is probably not desirable behaviour.

        Thanks,

      2. Tahir,

        2. Thanks for the explanation, if you’re only allowing selecting items from the list then allowEditingNewValues won’t be much help to you. I’ll add this to the list for a future version but I can’t promise this change any time soon (I personally like that once you select an item you can no longer edit it as text but I could see why people would want that behavior). If you’d like to implement it yourself in the source I’d be happy to help you out.

        3. Isn’t that how it’s supposed to work. For example, I just added some text to the search box on the top right in Firefox, highlighted it and pressed the spacebar. I was left with a single space.

        Thanks for the feedback!

  23. Hillel,

    I will see if I can go through the code and understand/change it.

    I could not reproduce it now from online demo. If it works this way with space character, it should do the same with any other character.

  24. I’ve modified code in AutoComplete.handleKeyDown towards the end and now it discards any values that don’t exist in the dataProvider. Please review.

    else if (event.keyCode == Keyboard.ENTER || event.charCode == 44)
    {
    if (target is EditableItem)
    {
    // we’re going to remove and then re-add it so that we
    // can run the unqiue check against it
    _selectedItems.removeItemAt( index );
    _selectedItems.addItemAt( EditableItem( target ).item, index );

    textInput.setFocus();
    }
    else if (target.text && _allowNewValues && target.isEditable())
    {
    _selectedItems.addItem( target.text );
    dispatchEvent( new Event( Event.CHANGE ) );
    return;
    }
    else if (event.keyCode == Keyboard.ENTER && !_allowNewValues)
    {
    textInput.setFocus();
    textInput.text = ”;
    }
    }
    else if (event.keyCode == Keyboard.TAB && target.text && !_allowNewValues)
    {
    textInput.setFocus();
    textInput.text = ”;
    }

  25. Hi Hillel,

    After using the below code:
    autoComplete.flowBox.height = 50;
    autoComplete.flowBox.verticalScrollPolicy = ScrollPolicy.AUTO;
    I am able to view the scroll bar.But the menu action item icon is getting hiding behind the scroll bar.
    Could you please suggest with some idea how to display the menu action icon before the scroll bar so that user able to view the menu action item icon.
    Regards,
    Sourav

  26. Hi Hillel, Excellent component. What is the easiest way to show a simple Label (text) below the last item in the dropdown list? How big of a change would that be?

    1. Anuj,

      Hmm… that’s an interesting one. What’s the purpose of the label/should it be clickable. We had considered adding a label to the bottom as a menu (ie, an add new item option) but in the end decided to create the actionsMenu feature to display a popUp menu.

      I haven’t tried this myself but here’s one possible solution.
      – Add the “label” as an item to your dataProvider and set a sort function so it always appears at the bottom.
      – Create a custom filterFunction which always returns true for this item.
      – If you don’t want it to be selectable make sure to remove it if the user selects it.

      Hope this helps/works,
      Hillel

      1. Hi Hillel,

        Thanks. Thats what I thought initially and that works. However, it would be great if the component can have 2 new writable properties (showMore=true/false and showMoreMessage=text) , that way we can control it from outside the component.

        Great work, anyways, Thanks.

  27. Hi, I hope somebody can help me…

    I would like the auto complete to work with a list from the server that changes everytime you type a new letter. But it should only go to the backend when there are more than 5 letters. So if you type 6 letters, the dropdown begins. This works if I do:

    protected function demandeKeyUpHandler():void{
    var demande:String = demandeAutoComplete.searchText;
    if(demande.length >= 6){
    // generate event to call backend and set the listofThings(the dataprovider)
    }
    }

    this works fine, but when you type 6 letters and remove some, the dropdown list is not being reset to nothing and still works for the dropdown list on the client(for the 6 letters). If there are less than 6 letters, I just set the listOfThings to an empty array. But then flex throws the following exception:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at com.hillelcoren.components.autoComplete.classes::DropDownItemRenderer/init()[/Users/hillel/Code/flex-autocomplete/src/com/hillelcoren/components/autoComplete/classes/DropDownItemRenderer.mxml:16]
    at com.hillelcoren.components.autoComplete.classes::DropDownItemRenderer/___DropDownItemRenderer_Label1_creationComplete()[/Users/hillel/Code/flex-autocomplete/src/com/hillelcoren/components/autoComplete/classes/DropDownItemRenderer.mxml:4]
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:9298]
    at mx.core::UIComponent/set initialized()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:1169]
    at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:718]
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8628]
    at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8568]

    If I look at the source, it does:
    _list = listData.owner as List;

    how can i reset the autocomplete component?
    Or which properties should i reset if i want to clean the list? Or is working with the keyUp event not the right way to change the list dynamically?

    thanks!
    Peter

    1. Peter,

      I’m not entirely sure what’s happening, but here are a couple of things to try.
      – Use the searchChange event to listen for changes to the TextInput
      – Call the removeAll function rather than setting it to an empty array

      Hope this helps,
      Hillel

      1. Thanks for the reply!

        To fix it, I first needed to call the remveAll method on the component, but I also needed to call removeAll on the list variable itself(the dataprovider).

        The only thing that does not work is that when you type the sixth letter, the searchChange is dispatched, and the list is retrived from the backend, but the dropdown box doesnt do anything. When you type the 7th letter, is starts. I tried calling the search() method after the list was set, but that does not trigger the component to start the search in the dataprovider that is just initialzed. Any idea?

        Thanks,
        Peter

      2. Peter,

        Calling the search method is the right thing to do, I’m not sure why it isn’t working. I’d suggest trying to use a callLater to call the search method, you shouldn’t need to do that but it’s worth trying just to see if it’s some sort of timing issue. Another thing to try is to call the validateNow function before calling the searchMethod.

      3. Thanks Hillel, it works now!

        I use the callLater method to call the search method.

        Peter

  28. I was wondering if it’s possible to simplify your code, so it will not style selected item at all, just a plain text, that’s all. Can that be done?

    1. Mark,

      I’m sorry, currently the component doesn’t support that. The challenge is as follows, in order to support selecting multiple items I’ve made each item a separate object (they’re actually buttons). If the items were plain text you’d expect it to word wrap but that would get rather tricky. If you don’t need to enable the user to select multiple items I’d suggest considering using Adobe’s AutoComplete component.

  29. Hello,
    firstly great component. Secondly – is there a way to use an xmlList as the dataprovider instead of an ArrayCollection? I have been trying to convert my xmlList into an ArrayCollection to use in you component but am not having much success.
    Thanks

    1. Scott,

      I’ve actually just added support for XmlListCollections to the component, you’ll need to checkout the swc/code from the google code site. If you’d like to convert your XML data to an arrayCollection I’ve actually written a post explaining how to do it.

      1. Hillel,
        thanks for the reply. I have gotten the XML data to work. My only question now is – I am using the colordemo and cant work out how to find the value of the entered information if it doesn’t match one in the list. I need to find out the information entered to use in other parts of my program. Could you point me in the right direction. Thanks

      2. Scott,

        It depends on your setting for the allowNewValues property:

        true – the value will be in the selectedItem/selectedItems property
        false – the value will be in the searchText property

    1. Eze,

      Happy to hear it saved you time. That’s what I’m hoping for, we shouldn’t need to build everything from scratch.

      Best,
      Hillel

  30. Hi there,

    First off… great component! I have one little glitch that I have found that I’m wondering if anyone else is sharing. Sometimes, when I click into the autocomplete text box to start typing, it won’t take focus, and I’ll have to click in the box twice to have it recognize. It seems pretty inconsistent.

    Any ideas?

    Best

    1. Malko,

      I haven’t seen that problem myself but someone else posted a comment a little while back reporting the same issue. I think they were using a different font, are you doing the same?

  31. Hi Hillel
    understand that you have added support for XmlListCollections to your nice component. unfortunately i can’t seem to find it in the new src?
    any help appreciated.
    thanks

    1. Mei,

      You should just need to use the AutoComplete SWC file in the bin folder.

      Here’s an example:

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application 
      	xmlns:mx="http://www.adobe.com/2006/mxml" 
      	xmlns:components="com.hillelcoren.components.*">
      
      	<mx:XML format="e4x" id="xml">
      		<items>
      			<item>one</item>
      			<item>two</item>
      		</items>
      	</mx:XML>
      		
      	<mx:XMLListCollection id="xmlList" source="{ xml.item }"/>
      		
      	<components:AutoComplete dataProvider="{ xmlList }"/>
      	
      </mx:Application>
      
      1. Hi Hillel
        thanks for the pointer. I am using the latest swc, but am getting the “Implicit coercion of a value of type mx.collections:XMLListCollection to an unrelated type mx.collections:ArrayCollection.” error.
        Is there something else that needs to be changed?
        thanks

      2. Mei,

        Hmmmm…. I’m not sure what the problem is. Here are a couple of thoughts:

        – I’ve just checked in a new SWC, please update and try again (maybe the old SWC didn’t have the changes in it?)
        – Have you tried doing a “clean build”
        – Could you tell me where the error is (maybe I missed something)

        Thanks,
        Hillel

  32. Hillel,

    I have another question. Is it possible to do the following with your component:
    My datasource has 3 fields: ‘id’, ‘label’, ‘text’
    – the component should use ‘text’ field to search for the entered text
    – the drop down list should display the ‘label’ field (I know it is possible using the dropDownLabelFunction property)
    – the selected item should be displayed using the ‘label’ field in the textinput component (this is what I don’t know how to do)

    Thanks!

  33. Hillel,

    Looking at the source code I guess the answer is no to my last question.
    What do you think about introducing a new property called searchField (and maybe a searchFunction as well).
    It could default to labelField.
    The labelField coud be used to display the selected item, and searchField coud be used to search for the entered text in.
    The reason I need it is that I need to search in company names. But a company can have different name variations, abbreviations, synonyms, etc. I need to be able to search in all these name variations, but the displayed name of the company must be its official name only.
    I think this addition might be useful in general for your component.

    Andras

    1. Andras,

      Try creating a dropDownItemRenderer to display the value in the dropDown (the name variation) and use the labelFunction to set the value for the selected item (the nice company name). The color chooser demo is a good example for how to create a dropDownItemRenderer.

      Hope this helps,
      Hillel

      1. Hillel,

        The problem is that the label or the labelfunction return value will be used to search for the text. So the same text will be used as label as for searching for the text. Looking at the source code these cannot be different.
        And in my case I need a different text to be used for the search than what will be used as label. That is the main thing.
        I created a modified version of your component, I added searchText to it and it is working fine. If you wish to see it I can send it to you.

      2. Andras,

        If you create a filterFunction you can have the component search by a field that’s different than the one that’s displayed as the label. You could then use the dropDownLabelFunction (or set a dropDownItemRenderer) to set the text that appears in the dropDown. Did this not work for you?

        I agree that it should be easier to set a different search field than label field, I hope to work on this in a future release.

  34. hi Hillel,

    Last time you had taught me how to use the inlineButton to show a down-arrow a la combobox. You wanted feedback on the same.

    I extended your component. In the sub-class, i use the following:

    public function inlineButtonClickHandler(evt:Event = null):void{
    if (dropDown && dropDown.parent){
    hideDropDown();
    }else{
    validateNow();
    if (selectedItem == null){
    search();
    }
    if(dataProvider && dataProvider.length > 0){
    if (dropDown){
    dropDown.rowCount = (dataProvider.length < _dropDownRowCount ? dataProvider.length : _dropDownRowCount);
    }
    showDropDown();
    }
    }
    }

    private function handleKeyDown( event:KeyboardEvent ):void{
    if (!(dropDown && dropDown.parent)){
    if (event.keyCode == Keyboard.DOWN){
    inlineButtonClickHandler(event);
    }
    }
    }

    1. and of course, in the beginning of the class:

      private var _dropDownRowCount:uint = 5;

      [Embed(source=”com/hillelcoren/assets/icons/down.png”)]
      [Bindable]
      public var iconSymbol:Class;

      public function ZyAutoComplete(){
      super();
      width = 200;
      dropDownRowCount = _dropDownRowCount;

      inlineButton = new Button;
      inlineButton.width = 22;
      inlineButton.height = 18;
      inlineButton.setStyle(‘icon’, iconSymbol);
      inlineButton.addEventListener(MouseEvent.CLICK, inlineButtonClickHandler);
      addEventListener( KeyboardEvent.KEY_DOWN, handleKeyDown );
      }

      1. Maneesh,

        Thanks, the code looks good. I’m hoping to make the show dropDown button part of the component in a future release, your code will be helpful.

  35. Great module, thanks for sharing this.
    I have a problem with clearing my autocomplete fields.
    After I submit my data I call the removeAll() method, but it looks like the text property still contains the data. Isn’t there a method that completely clears the input, and put the ‘prompt’ text back in place?

    Thanks

    1. Maarten,

      First off, I just want to make sure you’re calling autoComplete.selectedItems.removeAll(), I’ve seen people in the past try calling autoComplete.removeAll(). This will remove the selectedItems but if there is a search string set you’d also need to clear the searchText property. Note that if allowNewValues is set to true then the searchText value will automatically be added to the selectedItems list so you won’t need to also clear the searchText property. Also, in order to put the prompt back you’ll need to make sure the autoComplete no longer has the focus.

      Hope this helps

      1. Great, I knew I was missing something.
        and I already figured out the focus 🙂

        Thanks a lot for the quick reply

  36. The Actions Menu is a nice feature…can you provide the code for the sample application where you have both ‘browse’ and ‘remove all’…thanks again!

  37. Hillel,

    Thanks for sharing this code!!!

    I modified it for picking a country – with the country full name and the abbreviation displayed in the dropdown (ie “United States” and “US” are displayed together).

    I want the search to work on the full name, but I want the abbreviation to display when a country is selected (ie “US”). Is there an easy way to do that (and just for this case, I’ll be using the autocomplete in several different places and won’t necessarily need the same behavior in other places)?

    I’m new to Flex, so I apologize for not quite being able to understand all the code yet and see an obvious answer to my question. And… I tried to read everything, but couldn’t quite make it through all the comments to see if this has already been asked.

    Thanks,
    Monica

    1. Monica,

      Search by full name: You’ll need to create a custom filter function, something like:

      private function init():void
      {
      	autoComplete.filterFunction = filterFunction;				
      }
      			
      private function filterFunction( item:Object, searchStr:String ):Boolean
      {
      	return StringUtils.anyWordBeginsWith( item.fullName, searchStr );				
      }
      

      Display both names in the dropDown: It sounds like you’ve already got this working. You have two options here, you can either create a dropDownItemRenderer (see the ColorDemo code for an example) or set a custom dropDownLabelFunction (see the EmailDemo for an example). Using the dropDownItemRenderer will give you more control over the layout as the dropDownLabelFunction simply allows you to set an HTML string.

      Display short name once selected: If you take the steps above you can simply set the labelField to the short name.

      Let me know if any of this is unclear,
      Hillel

  38. hello Hillel,
    I am using the AdvancedAutoComplete component… it works fine but found an issue with this one where it works for Autocomplete component… when I assign an arraycollection like
    mycomponent.selectedItems = myArrayCollection;
    it does not show these as selected and does not show in the control… as stated before this one works with AutoComplete Component… can you please look into this.
    am I missing something here?

    thank you
    Anil

    1. Anil,

      I’m having trouble replicating your problem, here’s the test app I created.

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application
          xmlns:mx="http://www.adobe.com/2006/mxml"
          xmlns:components="com.hillelcoren.components.*"
          verticalAlign="middle">
      	
      	<mx:Script>
      		<!&#91;CDATA&#91;
      			import mx.collections.ArrayCollection;
      			
      			&#91;Bindable&#93;
      			public var items:ArrayCollection = new ArrayCollection( &#91;"one","two","three"&#93; );
      			
      			private function handleClick():void
      			{
      				ac.selectedItems = new ArrayCollection( &#91;"one"&#93; );
      				aac.selectedItems = new ArrayCollection( &#91;"one"&#93; );
      			}
      						
      		&#93;&#93;>
      	</mx:Script>
      	
      	<components:AutoComplete id="ac" dataProvider="{ items }"/>
      	<components:AdvancedAutoComplete id="aac" dataProvider="{ items }"/>
      	<mx:Button label="Click Me" click="handleClick()"/>	
      
      </mx:Application>
      

      Could you please try creating an example which demonstrates your issue.

      Thanks

  39. Hi Hillel,

    first of all, thanks for making this component available. I have used an older version and now recognized through TourDeFlex that there’s and update.

    THough what Piotr said about the Event.Change is true.(http://hillelcoren.com/2009/05/11/flex-autocomplete-version-0-98-2/#comment-638)
    It would be great to get this event no matter what the input is, in my case its not fired when the text field is changed to an empty value, I can only change a picked value. I use it in an app with a database, so deleting properties with ur component would be great 🙂

  40. Hello
    First , I think you’ve created an excellent component!!! I really enjoy working w/ it ,however
    I have encountered 2 difficulties-

    1.I Cant control the selected skin to simply display the same font/size as the non selected but with different colors (no rectangles/facebook/etc…) I’ve tried to use a custom skin but nothing works….maybe I am not skinning it properly? how should it be done?

    2.How do I know if a user simply entered a string of his own which is not on the dataProvider?

    Thanks in advance
    Afik

    1. Afik,

      1. I’m sorry I’m not sure I understand you, what do you mean by “non selected” (if an item isn’t selected then it isn’t shown). If you’re working with the skins I’d recommend checking out the CustomSkin.mxml file in the examples folder.

      2. It depends on what the allowNewValues properties is set to. If it’s set to false, then you’d know they just entered their own string b/c selectedItem would be null and the searchText property would have the string they entered. If it’s set to true, then the selectedItems should contain the string they entered (which won’t be in your dataProvider).

      Let me know if this is unclear

      1. Hello

        Thanks for the quick reply.

        What I meant is, I am trying to change the skin like in the examples (customSkin)…and I can’t change the font color/size in it…it simply ignores that…
        I want my skin for the selected values to look exactly like a regular text input but w/ a different color… (no underline/rectangles/etc)

        Thanks again

        Afik

      2. Afik,

        What about something like this…

        <components:AutoComplete selectedItemStyleName=”none” color=”#FF0000″/>

      3. Hello

        I offcourse have tried it…but what happens is that after I choose from the list,the selected item appears as white on white(blank) and only when I click on it , it displays it in red… I want it to simply be in red over white w/o clicking on it.

        Thanks
        Afik

      4. Afik,

        I’m sorry, I’m not able to replicate your issue. Is it possible that you have some other code which is causing the text to appear as white. Also, could you please make sure you’re using the latest version from the google code site. Here’s the application I’m using to test it.

        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application 
        	xmlns:mx="http://www.adobe.com/2006/mxml"
        	xmlns:components="com.hillelcoren.components.*"
        	verticalAlign="middle" horizontalAlign="center">
        	
        	<mx:Script>
        		<!&#91;CDATA&#91;
        			import mx.collections.ArrayCollection;
        			
        			&#91;Bindable&#93;
        			private var _data:ArrayCollection = new ArrayCollection( &#91;"one"&#93; );
        		&#93;&#93;>
        	</mx:Script>
        	
        	<components:AutoComplete dataProvider="{ _data }" selectedItemStyleName="none" color="#FF0000"/>
        	
        </mx:Application>
        
    2. Hi Afik,

      I am having the exactly same problem with the color. Are you able to resolve this issue or not. I am also using the latest code from the site. Pls let me know
      the required solution if you were able to find out.
      Thanks,
      Ravi

  41. Hi Hillel,

    i’ve only just noticed that the filtering function took into account accents, among other things. Being as I work in a french environment and the french language having accents, I would need to be able to match elements regardless of accents (for the lazy people not putting accents in their search text). I tried modifying the filterfunction by upper casing both the search text and the dataprovider’s items but the upper casing keeps the accent, thus not returning a match.
    Any thoughts?
    thanx in advance
    Pier

    1. Pier,

      I created a small Flex app that used hebrew and ran into a similar problem (I’m assuming french also uses multibyte characters). I wrote the following PHP function to strip the accents (it just takes the first byte from each character). I’m sorry, I’m not sure how to convert this to ActionScript.

      function stripAccents($b)
      {
      $word = “”;

      for ($i=0; $i < mb_strlen($b, 'UTF-8'); $i++) { $ch = mb_substr($b, $i, 1, 'UTF-8'); $chlen = mb_strwidth($ch, 'UTF-8'); $hexs = ''; for ($j=0; $j < $chlen; $j++) { $hexs = $hexs . sprintf("%x", ord($ch[$j])); } $html = utf8_to_html($ch); if ($hexs == "d7" || $html == "־") { $word .= $ch; } } return $word; } [/sourcecode] Hopefully this is some help...

      1. Thanks but i ended using something else, in AS.
        Here’s the code (fyi, it’s for french accents) (hope this comes out right)

        <pre name=”code” class=”php”>

        private function stripAccents(str:String):String
        {
        var rExps:Array = [{ re: /[\xC0-\xC6]/g, ch: ‘A’ }, { re: /[\xE0-\xE6]/g, ch: ‘a’ }, { re: /[\xC8-\xCB]/g, ch: ‘E’ }, { re: /[\xE8-\xEB]/g, ch: ‘e’ }, { re: /[\xCC-\xCF]/g, ch: ‘I’ }, { re: /[\xEC-\xEF]/g, ch: ‘i’ }, { re: /[\xD2-\xD6]/g, ch: ‘O’ }, { re: /[\xF2-\xF6]/g, ch: ‘o’ }, { re: /[\xD9-\xDC]/g, ch: ‘U’ }, { re: /[\xF9-\xFC]/g, ch: ‘u’ }, { re: /[\xD1]/g, ch: ‘N’ }, { re: /[\xF1]/g, ch: ‘n’ }, { re: /[‘ç’]/g, ch: ‘c’ }];

        for (var i:int = 0; i < rExps.length; i++)
        {
        str = str.replace(rExps[i].re, rExps[i].ch);
        }
        return str;
        }

        </pre>

        so that works to strip the accents. I then put that in my filter function and it works except for one little thing: when i type letters, it recognizes the match correctly, but the displayed choice in the drop down box is not highlighted correctly and for each letter i type, a letter is deleted from the drop down display. Odd….

      2. Pier,

        Happy to hear you figures it out, thanks for sharing the solution. To resolve your issue you may need set a custom dropDownLabelFunction. The email demo has a good example in it.

      3. Hillel,
        thanx for pointing me in the right direction.
        I’ve finally been able to get the behavior i wanted.

        Basically, to implement the accent-insensitive behavior, i have a new filterFunction (which compares two accent free strings), i modified the highlightMatch function (which now matches two accent free strings), and a function stripping accents off a string.

        I added the stripAccents function to the StringUtils class (so that the highlightMatch function can access it).
        To correct the bug on the dropdown, i had to modify the highlightMatch function as it was comparing a string with accents to one without accents, thus returning no match yet still building a return string with an odd character in it. I basically just added the call to the stripAccents function to the matchPos variable as such

        var matchPos:int = stripAccents(string).toLowerCase().indexOf(stripAccents(searchStr).toLowerCase());

        quick remark: at first i was planning on just redifining a new dropDownLabelFunction but i ran into a problem as it only takes the item in paramater and not the searchText. In the defaultDropDownLabelFunction in the AutoComplete class, you retrieve the searchText by taking the global variable of the AutoComplete. but when redefining the function, if i have several autocompletes in my page, i can’t use a generic dropDownLabelFunction. Hence, i modified the highlightMatch in the StringUtils class rather than redefining my own.
        Not sure if all of that is clear.
        Let me know if you need any more precisions

        Pier

      4. Pier,

        Thanks for explaining your solution, I’m happy to hear that you were able to get it working. That all makes sense, I’ll add the search text to the dropDownLabelFunction in the next release.

      5. my pleasure Hillel.
        By the way, you misspelled the name of the function “highlighMatch” (a “t” is missing) 😉

  42. Hillel ,

    Can I insert checkBox in actionsMenuDataProvider? I would like to put group of checkBox in this. Please suggest.

  43. Dataprovider gets reset when using autocompletion?

    I have experienced a strange behaviour. When I use the auto-complete feature to select an item from the dataprovider, it gets added to the list, but sometimes the dataprovider now contains only this item – all others are gone?

    Any ideas, or others how have experienced the same problem?

    Thx,
    martin

  44. I can now reproduce it:

    If you use the autocomplete with the enter function, everything works fine.

    But if I type something, and then choose one item from the suggested ones with the mouse, it seems that a filter is applied to the array collection of the dataprovider and only the matching items are displayed anymore.

      1. Hi Hillel,

        no, I did not get the replicate it in the demo. Maybe it is specific in my application – however, the filter of the dataprovider is set to: after the click on an item was made.
        I solved it be setting the filter manually to null and refresh the dataprovider, but I wonder where this filter comes from. Initially you put one on the dataprovider to show the matches in the autosuggest box, no? But where do you remove it again?

        Thx,
        martin

      2. Martin,

        Once the filterFunction is set we don’t remove it. The default filterFunction starts with the following lines of code which ensure if the search is blank that all items are visible. Not having this in your custom filter function may be the source of your problem.

        if (searchStr.length == 0)
        {
        	return true;
        }
        

        If you’re able to put together a test application which demonstrates the issue I’d be happy to debug it for you.

  45. Great component, but I’m facing a problem:

    I have two database tables, one for users, one for user groups. Then, in a user form, I want a autocomplete that will search the user groups name from the user groups table and display them.

    This requires a remote access and the dataprovider changing each time a response is received from the server.

    There is a bug where changing the dataProvider with itens added to autocomplete throws an exception (I think this is because that item is not available anymore in dataProvider array, because the server replaced it by a new one, sometimes an empty one).

    The exception is:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at com.hillelcoren.components.autoComplete.classes::DropDownItemRenderer/init()[/Users/hillel/Code/flex-autocomplete/src/com/hillelcoren/components/autoComplete/classes/DropDownItemRenderer.mxml:16]
    at com.hillelcoren.components.autoComplete.classes::DropDownItemRenderer/___DropDownItemRenderer_Label1_creationComplete()[/Users/hillel/Code/flex-autocomplete/src/com/hillelcoren/components/autoComplete/classes/DropDownItemRenderer.mxml:4]
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.3.0\frameworks\projects\framework\src\mx\core\UIComponent.as:9308]
    at mx.core::UIComponent/set initialized()[C:\autobuild\3.3.0\frameworks\projects\framework\src\mx\core\UIComponent.as:1169]
    at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.3.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:718]
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.3.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8633]
    at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.3.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8573]

    How that’s done?

    1) A timer (250ms) send a HTTP request for my server (ASP.Net MVC)
    2) The server searchs my user groups that contains the search text and returns to client via XML
    3) The component doesn’t bind with XML 😦 so, for each ID/Name returned, I insert them into a ArrayCollection then bind this to the autocomplete (component.dataProvider = variable).

    Works fine, except if I search something that not returns items from the previous search. Ex.: I search “Admini” and put “Administrators” on the list. Now, I search for “Mana”, wich returns “Managers”. When .ShowDropDown() is invoked, the exception raises (I think because the new .dataProvider array does not contains “Administrators” anymore.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s