CFGRID Cell Renderer - ComboBox (Select)
Posted By : todd sharp Posted At : June 12, 2006 8:32 PM Posted In: Flash Forms, ActionScript, ColdFusion
23
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:
<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.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;
}
}



Are you saving ComboBoxCell.as in the same directory as the cfm page? Did you make any changes to the ComboBoxCell.as file? If there are errors in the Actionscript code the form won't load (and it won't give you an error sometimes either) :(
Post your AS code here if you've made changes and I'll see if I can spot any errors.
Check out my post tomorrow morning - I'll show how to populate with a query.
todd
I'm using MX7 on a Windows XP machine. Nothing else is in either file except for the code above.
What am I missing? Thanks!
Has anyone run into a problem, when using a dynamic source for the combo box, of the Grid rendering and being presented without the combo box? It seems that the combo box only appears about 1/3 of the time. Is there something I need to use to "slow down" the rendering of the grid until after the combo box has been created?
Once we do settle on a UI, I will be re-writing those code tables, but was basically checking to make sure I wasn't alone, or if someone had a silver bullet to solve my problem.
Thanks!!
I have a cfgrid bound to a cfc. It'll have one (and only one) editable column, ActiveStateID, which will be a select box on each row. My attempt to do this includes:
<cfgrid selectmode="edit" format="html" [snip] >
<cfgridcolumn name="ActiveStateID" header="State" select="yes" display="yes" values="1,2,3" valuesdisplay="Active,Enabled,Paused">
[snip]
</cfgrid>
The problem is that this gives me an ActiveStateID column containing the integer values of the foreign key (1, 2, or 3) instead of select boxes with Active, Enabled, and Paused and the correct option selected.
Ideas...?
http://www.danvega.org/blog/index.cfm/2008/3/12/Cu...
Hope that helps.
1. The dropdown only works if the the cell is empty.
2. once a selection is made and the DB is updated the dropdown stops working and the cell becomes uneditable.
At least this has been my experience. Anyone find a way to work around this?
I can't seem to rename the file to anything else, not even renaming the classes seem to work.
I can't put it in a sub directory because there is no way to reference it (that I can find).
I can't seem to put both the new page, and the new comboboxcell.as in a new sub directory, because it pulls the comboboxcell.as from the directory above.
I can't seem to just copy and paste the code into a script form item, because then nothing loads.
I am totally out of ideas. How can I have another combobox?! Thanks for any help, I really appreciate it. By the way, your code does rock, the other page where I am already using it works like a dream, I love it (hence the reason I want it so badly on this other page!).