Multiselect ComboBox

Well, there may be requirement that you have to make combobox to act as listbox. Got what I am saying? Ok. In a combobox at any point of time, you can only select one value but sometimes based on need, you may have to select multiple values which actually is the job of listbox. This could be because of space issues in the page or some UI design or whatsoever. The combobox component provided by flex does not allow you to select multiple values. To achieve this, you need to extend combobox class and add your functionality to your custom class. Ofcourse its very simple to convert single value selection to mutivalue selection. Here you go.


Multiselect ComboBox



Lets see what changes you need to make, to make this happen and in just 4 steps.

Step 1: Create your own custom class that extends ComboBox class.

public class CustomMultiSelectComboBox extends ComboBox {

	/*
	 * Constructor
	 */		
	public function CustomMultiSelectComboBox(){
		super();
	}
	
	.....

}

Step 2: To select multiple values, generally you hold down control key and then select the required values from the ComboBox dropdown. So you need to capture this in the custom class like below. Here you should override "keyDownHandler" and "keyUpHandler" functions that are provided by "ComboBox" class. In "keyDownhandler" function, when you press control key, the property "allowMultipleSelection" of "ListBase" class (dropdown is instance of ListBase) is set to true. This allows you to select multiple values and "selectedItems" property of the "dropdown" will be set with selected values. In the "keyUpHandler" function, check if you are still holding control key and if not, close the dropdown and dispatch "ListEvent.CHANGE" event. Handling this event is done in next step. You can set the selected index to -1 if you dont want to show the last selected value. Also you can override the "close" function provided by "ComboBox" class. This is to set the selected index to -1 and if you dont want to set the selected value to first value when the dropdown is closed, you dont need to override this function.

private var ctrlKey:Boolean = false; //Control Key Pressed

/**
 * This function checks whether the CtrlKey is pressed.
 * If CtrlKey is pressed then, multiple selection is enabled for the ComboBox dropdown.
 */
override protected function keyDownHandler( event:KeyboardEvent ):void {
	super.keyDownHandler( event );
	
	this.ctrlKey = event.ctrlKey;
	
	if( this.ctrlKey == true ) {
		dropdown.allowMultipleSelection = true;
	}
}

/**
 * If any key other than CtrlKey is pressed then, 
 * ComboBox dropdown (a list component) is closed and change event is dispatched.
 */
override protected function keyUpHandler( event:KeyboardEvent ):void {
	super.keyUpHandler( event );
	this.ctrlKey = event.ctrlKey;
	
	if ( this.ctrlKey == false ) {
		this.close(); 
		var changeEvent:ListEvent = new ListEvent( ListEvent.CHANGE );
		this.dispatchEvent( changeEvent );
		this.selectedIndex = -1;
	}			
}

/**
 * This function prevents the ComboBox from closing if CtrlKey is pressed on a Close Event
 */
override public function close( trigger:Event=null ):void {

	if( this.ctrlKey == false )	{
		super.close( trigger );
		this.selectedIndex = -1;
	}
}

Step 3: In Step 2, you dispatched "ListEvent.CHANGE" when the control key is released. Now you need to listen the CHANGE event and return the multiple values you selected by holding control key. Its very simple. Add the below getter function to the custom class you created and return "selectedItems" property of the dropdown which is nothing but array of values and bind it with the "change" event. So anytime you release the control key, "CHANGE" event is dispatched and this function is called as it is the listener function and returns the selected values. Also add below setter function for selectedItems and then set the selected array values to selectedItems property of dropdown.

/**
 * Setter function for selectedItems
 */
public function set selectedItems( values:Array ):void {
	if( this.dropdown ) {
		this.dropdown.selectedItems = values;
	}
}


/**
 * Getter function for selectedItems
 */
[Bindable("change")]
public function get selectedItems( ) : Array {
	if ( this.dropdown ) {
		return this.dropdown.selectedItems
	} else {
		return null;
	}	
}

You may sometime need the selected indices apart from selected ietms. In that case, add below two setter and getter functions to get the selected indices and they are similar to selectedItems functions.

/**
 * Setter function for selectedIndices
 */
public function set selectedIndices( value:Array ) : void {
	if ( this.dropdown ) {
		this.dropdown.selectedIndices = value;
	}
}


/**
 * Getter function for selectedIndices
 */
[Bindable("change")]
public function get selectedIndices( ) : Array {
	if ( this.dropdown ) {
		return this.dropdown.selectedIndices;
	} else {
		return null;
	}
}

Step 4: Now final step - using the custom ComboBox in your mxml file, as simple as it is.

<mx:Application 
	xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="absolute" 
	xmlns:CustomCombo="*" 
	horizontalAlign="center" 
	verticalAlign="middle" >

	<CustomCombo:CustomMultiSelectComboBox id="multiSelectComboBox" 
				dataProvider="{this.stateArray}" 
				labelField="name" prompt="Select States.."/>

</mx:Application>


Thats all. Simple custom class. You can download the example source code here.

Download the example code.





blog comments powered by Disqus