Fixing The ComboBox Cell Renderer Weirdness
Last week I posted an issue with some cell renderer weirdness when rows were added to the grid and the grid was scrolled. Apparently the grid actually "recycles" the renderer, thus reusing whatever selectedItem was in the same spot in the grid when scrolled. The fix was actually quite simple, but I thought I would share it for anyone experiencing the same problem.
Here is the AS file for the renderer. For the complete example, see the related posts below.
import mx.core.UIComponent
import mx.controls.ComboBox
class ComboBoxCellNew extends UIComponent
{
var combo : MovieClip;
var owner : MovieClip;
var listOwner : MovieClip;
var getCellIndex : Function;
var getDataLabel : Function;
function ComboBoxCellRenderer()
{
}
function createChildren(Void) : Void
{
//Creates a ComboBox object and listen to changes
combo = createObject("ComboBox", "Combo", 0, {styleName:this, owner:this});
combo.addEventListener("change", this);
combo.labelField = "priority";
combo.dataProvider = _global.COMBOBOX_DATA_PROVIDER;
size();
}
// note that setSize is implemented by UIComponent and calls size(), after setting // __width and __height
function size(Void) : Void
{
var h = __height;
var w = __width;
combo.setSize(w - 2, Math.max(h, listOwner.rowHeight - 2));
}
public function setValue(str:String, item:Object, sel:Boolean) : Void
{
/* Sets the ComboBox to the correspoinding cell data from the list owner's data provider if the cell data matches
with any items available for the ComboBox. */
var drawCombo:Boolean = true;
if (item[getDataLabel()]!=undefined)
{
/* For each item's data in the ComboBox, verify if it matches
the assigned data for the cell this ComboBox is in.
Set the selectedIndex of the ComboBox to what matches. */
for(var i:Number = 0; i < combo.length; i++)
{
if( combo.getItemAt(i).priority == item[getDataLabel()] )
{
combo.selectedIndex = i;
break;
}
if ( i == combo.length - 1 )
{
//****THE FIX*** if the combobox has no length (on an insert) - set the selected index to 0 (the first item) combo.selectedIndex = 0;
}
}
}
else
{
// There was no data, set the combobox to blank combo.selectedIndex = 0;
}
combo._visible = drawCombo;
}
function getPreferredHeight(Void) : Number
{
return owner.__height;
}
function getPreferredWidth(Void) : Number
{
return owner.__width;
}
// This re-build the dataProvider, the selected item // as the first in the array function reorder(datos:Array, choice:String):Array {
var index:Number = 0
var newArray = new Array()
for(var i=0; i<datos.length; i++){
if(datos[i].label!=choice){
index++
newArray[index] = datos[i]
} else newArray[0] = datos[i]
}
return newArray
}
public function change()
{
// Handler for the ComboBox change event.
// Set the listOwner's data to the currently selected item's data of the combo box. listOwner.dataProvider.editField(getCellIndex().itemIndex, getDataLabel(), combo.selectedItem.priority);
listOwner.selectedIndex = getCellIndex().itemIndex;
}
}
import mx.controls.ComboBox
class ComboBoxCellNew extends UIComponent
{
var combo : MovieClip;
var owner : MovieClip;
var listOwner : MovieClip;
var getCellIndex : Function;
var getDataLabel : Function;
function ComboBoxCellRenderer()
{
}
function createChildren(Void) : Void
{
//Creates a ComboBox object and listen to changes
combo = createObject("ComboBox", "Combo", 0, {styleName:this, owner:this});
combo.addEventListener("change", this);
combo.labelField = "priority";
combo.dataProvider = _global.COMBOBOX_DATA_PROVIDER;
size();
}
// note that setSize is implemented by UIComponent and calls size(), after setting // __width and __height
function size(Void) : Void
{
var h = __height;
var w = __width;
combo.setSize(w - 2, Math.max(h, listOwner.rowHeight - 2));
}
public function setValue(str:String, item:Object, sel:Boolean) : Void
{
/* Sets the ComboBox to the correspoinding cell data from the list owner's data provider if the cell data matches
with any items available for the ComboBox. */
var drawCombo:Boolean = true;
if (item[getDataLabel()]!=undefined)
{
/* For each item's data in the ComboBox, verify if it matches
the assigned data for the cell this ComboBox is in.
Set the selectedIndex of the ComboBox to what matches. */
for(var i:Number = 0; i < combo.length; i++)
{
if( combo.getItemAt(i).priority == item[getDataLabel()] )
{
combo.selectedIndex = i;
break;
}
if ( i == combo.length - 1 )
{
//****THE FIX*** if the combobox has no length (on an insert) - set the selected index to 0 (the first item) combo.selectedIndex = 0;
}
}
}
else
{
// There was no data, set the combobox to blank combo.selectedIndex = 0;
}
combo._visible = drawCombo;
}
function getPreferredHeight(Void) : Number
{
return owner.__height;
}
function getPreferredWidth(Void) : Number
{
return owner.__width;
}
// This re-build the dataProvider, the selected item // as the first in the array function reorder(datos:Array, choice:String):Array {
var index:Number = 0
var newArray = new Array()
for(var i=0; i<datos.length; i++){
if(datos[i].label!=choice){
index++
newArray[index] = datos[i]
} else newArray[0] = datos[i]
}
return newArray
}
public function change()
{
// Handler for the ComboBox change event.
// Set the listOwner's data to the currently selected item's data of the combo box. listOwner.dataProvider.editField(getCellIndex().itemIndex, getDataLabel(), combo.selectedItem.priority);
listOwner.selectedIndex = getCellIndex().itemIndex;
}
}



e.g.;
row1 [state1][dropdown cities of state1]
row2 [state2][dropdown cities of state2]
is this possible?
i have experimented on it and being a novice in flash forms and flash actionscript i can't seem to make it work.