Custom Flex ComboBox that filters data provider based on user input

I have a ComboBox, and the data provider is an ArrayCollection of 3 values: CA - California, NY - New York, TX - Texas. With the default behavior, when I start typing in a ComboBox, it will try to match the value from the beginning of the line, so if I start typing in TX, it will output TX-Texas.

I want to be able to search in any part of the string, not just from the beginning, so if I type "xas" it will filter the selection and display only TX-Texas. There is a very useful post on the Adobe forums on how to do this by changing the filter function to ArrayCollection, which provides data for the ComboBox and I adapted it, but I have a little problem with it.

If the user selects a value and then tries to enter new text, the first letter entered in the ComboBox is not displayed.

1) Select CA - California in ComboBox
2) Highlight the text and press "n" on the keyboard
3) You expect to see the text field filled with "n", but the text field remains empty

What could be causing this problem? This only happens if you have already selected a value. If you start with a clean ComboBox, it works as expected.

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

        import spark.events.TextOperationEvent;

        [Bindable]
        public var arrC:ArrayCollection = new ArrayCollection([{label:'CA - California'},{label:'NY - New York'},{label:'TX - Texas'}]);

        private function changeHandler(e:*):void
        {
            if (arrC.filterFunction != doFilter)
                arrC.filterFunction = doFilter;
            arrC.refresh();
        }

        private function doFilter(item:Object):Boolean
        {
            if(String(item.label).toLowerCase().indexOf(cb.textInput.text.slice(0 ,cb.textInput.selectionAnchorPosition).toLowerCase())>-1)             
            {
                return true;
            }
            return false;
        }                       

        protected function application1_creationCompleteHandler(event:FlexEvent):void
        {
            cb.textInput.addEventListener(TextOperationEvent.CHANGE,changeHandler );
        }

    ]]>
</fx:Script>

<s:ComboBox id="cb" dataProvider="{arrC}"/>
+3
source share
1 answer

You have a solution for your problem (because I had to develop a custom component similar to googles search input field). It seems that normal input processing gets wrong by filtering the data provider. However, I did not investigate the sources of unexpected behavior as deep as necessary to give a reasonable explanation of the causing problem (the idea of ​​a possible solution came too quickly;)). There he is:

<?xml version="1.0" encoding="utf-8"?>
<s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx"
        skinClass="CGoogleComboSkin">
<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.collections.IList;

        import spark.events.TextOperationEvent;

        private var unfilteredDataProvider : IList;
        override public function set dataProvider(value:IList):void {
            super.dataProvider = value;

            unfilteredDataProvider = value;
        }

        override protected function textInput_changeHandler(
                event:TextOperationEvent):void {
            super.textInput_changeHandler(event);

            if (unfilteredDataProvider is ArrayCollection) {
                ArrayCollection(unfilteredDataProvider).filterFunction = filterMatches;
                ArrayCollection(unfilteredDataProvider).refresh();

                super.dataProvider = new ArrayCollection(unfilteredDataProvider.toArray()); 
            }
        }

        protected function filterMatches(item:Object):Boolean {
            if (item is String) {
                if(String(item).toLowerCase().indexOf(
                    textInput.text.slice(0,
                        textInput.selectionAnchorPosition).toLowerCase())>-1)
                    return true;
            }
            else if (labelField && labelField!= "") {
                if(item.hasOwnProperty(labelField) && 
                        String(item[labelField]).toLowerCase().indexOf(
                        textInput.text.slice(0,
                        textInput.selectionAnchorPosition).toLowerCase())>-1)
                    return true;
            }

            return false;
        }
    ]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>

Combobox -, dataprovider , combobox (- , ). , , ;)

+7

All Articles