As promised in my last post, here is an example of creating a custom cell renderer for a select in a cfgrid. To be fair, the code isn't my own (though I can't seem to find where I originally found it. This example is purely to show that the custom renderer can be applied to a cfgrid within a Flash Form and can easily be customized to meet your individual needs.
The dataprovider is hardcoded in this example, but I imagine it could easily be dynamic with a little Flash remoting. The cool thing is that existing grid data item is pre-selected if it exists in the select's dataprovider. In the example, you'll also see that when the selected item changes, the data is populated in the appropriate grid cell.
Here's the code - first the cfm page:
<cfform format="flash" name="test" onload="setCellRenderer();">
<cfformitem type="script">
function setCellRenderer(){
testGrid.getColumnAt(2).cellRenderer = ComboBoxCell;
}
</cfformitem>
<cfformitem type="spacer"/>
<cfformgroup type="horizontal">
<cfgrid name="testGrid" width="260" selectmode="edit">
<cfgridcolumn name="dataCol" header="data col" width="100">
<cfgridrow data="data,low">
<cfgridrow data="data,medium">
<cfgridrow data="data">
<cfgridcolumn name="sel" header="select" width="200">
</cfgrid>
<cfinput type="button" name="testbtn" value="Show Value in Grid" onclick="alert(testGrid.selectedItem.sel);">
</cfformgroup>
</cfform>
Now the ComboBoxCell.as - residing in the same directory as the cfm page:
import mx.core.UIComponent
import mx.controls.ComboBox
class ComboBoxCell extends UIComponent
{
var combo : MovieClip;
var owner : MovieClip; // The row that contains the cell.
var listOwner : MovieClip; // the reference we receive to the list
var getCellIndex : Function; // the function we receive from the list
var getDataLabel : Function; // the function we receive from the list
private static var COMBOBOX_DATA_PROVIDER : Array = [{label:"", data:""},
{label: "unrated", data: "unrated"},
{label: "low", data: "low"},
{label: "medium", data: "medium"},
{label: "high", data: "high"}];
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.dataProvider = 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).data == item[getDataLabel()] )
{
combo.selectedIndex = i;
break;
}
if ( i == combo.length - 1 )
{
// There was no matching data, the ComboBox should not be shown.
//drawCombo = false;
// The original function hid the combobox if no data, i leave it in
}
}
}
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-builds 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.data);
listOwner.selectedIndex = getCellIndex().itemIndex;
}
}
Live Example.