How to select an item of mx:ComboBox on the basis of substring entered through keyboard

StackOverflow https://stackoverflow.com/questions/19354769

  •  30-06-2022
  •  | 
  •  

Domanda

I am using <mx:ComboBox /> and I want to select a matching item on the basis of string entered through keyboard. Currently, <mx:ComboBox /> selects the first matching item based on the first character only. I want this functionality to be customized. I am unable to find that KeyboardEvent listener which does the matching so that I can override it.

È stato utile?

Soluzione

To do this yourself, you should look at the following bits and pieces of code below from the ComboBox and ListBase classes. ListBase is what the ComboBox component uses for it's drop down list.

The ComboBox appears to be deferring the keyboard input to the drop down list. It then listens for events from the drop down list to know when the selection has changed (as a result of keyboard or mouse input).

Flex components usually override a method called keyDownHandler() to process the keyboard input when they have focus. Starting there, we come across ComboBox line 2231:

// Redispatch the event to the dropdown
// and let its keyDownHandler() handle it.

dropdown.dispatchEvent(event.clone());
event.stopPropagation();

So now the keyDownHandler() in the drop down list will get executed. That method has a giant switch statement, where the default case statement on line 9197 of ListBase looks like this:

default:
{
    if (findKey(event.charCode))
        event.stopPropagation();
}

This is where the drop down list decides what to select based on keyboard input (when the input is not an arrow key or page up, etc.). The protected findKey() method simply calls the public findString() method to do this work.

So to override this behavior yourself:

  • extend the ListBase class and override the findKey() or findString() methods with your custom logic
  • extend ComboBox class and override the createChildren() method so you can instantiate your custom ListBase class instead of the default one.

Altri suggerimenti

Here is the class which I've used in order to make it work. searchStr is user inputted string which needs to be matched. If no dataprovider item gets matched to the searchStr, the overridden listener falls back to the default behaviour. I am using Timer to flush the inputted searchStr after 2 seconds. The possible drawback is that it is assuming the dataprovider to be a collection of String values. But you can modify it accordingly as the need may be.

public class CustomComboBox extends ComboBox
    {
        private var searchStr:String="";
        private var ticker:Timer;
        public function CustomComboBox()
        {
            super();
            ticker = new Timer(2000);
            ticker.addEventListener(TimerEvent.TIMER, resetSearchString);
        }

        override protected function keyDownHandler(event:KeyboardEvent):void
        {
            super.keyDownHandler(event);

            // code to search items in the list based on user input.
            // Earlier, the default behavior shows the matched items in the dropdown,  based on first character only.
            // user input is invisible to user.
            if((event.charCode>=0x20 && event.charCode<=0x7E) || event.charCode==8)             //Range of printable characters is 0x20[space] to 0x7E[~] in ASCII. 8 is ASCII code of [backspace].
            {
                ticker.reset();
                ticker.start();

                if(event.charCode==8)
                {
                    if(searchStr=="")
                        return;
                    searchStr = searchStr.substr(0, searchStr.length-1);
                }
                else
                {
                    searchStr += String.fromCharCode(event.charCode);
                    searchStr = searchStr.toLowerCase();
                }
                for each(var str:String in dataProvider)
                {
                    if(str.toLowerCase().indexOf(searchStr, 0)>-1)
                    {
                        this.selectedItem = dropdown.selectedItem = str;
                        dropdown.scrollToIndex(dropdown.selectedIndex);

                        break;
                    }
                }
            }
        }


        /**
         * reset the search string and reset the timer.
         **/ 
        private function resetSearchString(evt:TimerEvent):void
        {
            searchStr = "";
            ticker.reset();
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top