CFGRID ComboBox Cell Renderer - Dynamic Query

As a follow up to my original post, here's an example of creating a combobox cell renderer for a cfgrid which is populated with a query rather than a hardcoded dataprovider. The trick is to use flash remoting to get the query, set a global variable containing the results, then call the renderer and use the global variable to set the combobox dataprovider.

The example still looks the same, but obviously this method is much more dynamic. There is one change in the AS file for the renderer. Since we're using a query from remoting, we can't access combo.selectedItem.data. Instead, we reference the column name from the query - in this case it's combo.selectedItem.priority.

Update: Download the Code.

selectRendererWithQuery.cfm

<cfform format="flash" name="testForm" onload="getSelectData();">
<cfformitem type="script">

function getSelectData(){
   //create connection    <cfoutput>
   var connection:mx.remoting.Connection = mx.remoting.NetServices.createGatewayConnection("http://#cgi.HTTP_HOST#/flashservices/gateway/");
   </cfoutput>
   //declare service    var myService:mx.remoting.NetServiceProxy;

   var responseHandler = {};
   var COMBOBOX_DATA_PROVIDER = COMBOBOX_DATA_PROVIDER;
   
   responseHandler.onResult = function( results: Object ):Void {
      //when results are back, populate the COMBOBOX_DATA_PROVIDER       //then set the cellRenderer       _global.COMBOBOX_DATA_PROVIDER = results;
      _root.testGrid.getColumnAt(2).cellRenderer = ComboBoxCellNew;
   }

   responseHandler.onStatus = function( stat: Object ):Void {
      //if there is any error, show an alert       alert("Error while calling cfc:" + stat.description);
   }
   
   //get service    myService = connection.getService("blog.tips.cellRendererSelect", responseHandler );
   //make call    myService.getPriorities();      
   }
</cfformitem>
   <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="check" header="check box" width="200">
</cfgrid>
       <cfinput type="button" name="testbtn" value="Show Value in Grid" onclick="alert(testGrid.selectedItem.check);">
   </cfformgroup>
</cfform>

cellRendererSelect.cfc

<cfcomponent name="cellRendererSelect" access="public" description="Gets Data for the cell Renderer Select">

<cffunction name="getPriorities" output="false" description="Returns a query" access="remote" returntype="query">
   
   <cfset qPriorities = queryNew("priority")>
   <cfset temp = queryAddRow(qPriorities, 4)>
   <cfset temp = querySetCell(qPriorities, "priority", "", 1)>
   <cfset temp = querySetCell(qPriorities, "priority", "low", 2)>
   <cfset temp = querySetCell(qPriorities, "priority", "medium", 3)>
   <cfset temp = querySetCell(qPriorities, "priority", "high", 4)>
   
   <cfreturn qPriorities />
</cffunction>

</cfcomponent>

ComboBoxCellNew.as

import mx.core.UIComponent
import mx.controls.ComboBox

class ComboBoxCellNew 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    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 )
            {
               // There was no matching data, the ComboBox should not be shown.                //drawCombo = false;             }
         }
      }
      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;
   }

}

Related Blog Entries

Comments
having a little trouble copying the code into a new page... the single-line comments and line breaks aren't working which forces me to guess where the comment ends (particularly in the AS file)
# Posted By Michael White | 6/30/06 8:03 AM
Yeah, I should probably start putting up zip files so the code could be downloaded easily. I'll throw one up for this later today.
# Posted By todd | 6/30/06 8:25 AM
Just updated the post to add a zip so you can download the code.
# Posted By todd | 6/30/06 9:19 AM
Code downloaded: you da man!
# Posted By Michael White | 6/30/06 3:52 PM
Hi,

I read your previous post and it has helped tremendously for hard-coding a dataprovider. I was wondering however, is this technique also possible to do without remoting? Can a combo box be placed in a cfgrid and populated via a cfquery without remoting??

Thanks!
# Posted By Ray Manalo | 7/6/06 8:17 AM
Thanx allot for that example, I have found a buggy problem though. When I replaced the static query with a db query, the select boxes only seem to show like 50% of the time, when I refresh the page. Not sure where to even start debugging.
# Posted By Oliver | 7/6/06 7:00 PM
It seems the page can run faster than the query. when I tossed in a cachedwithin in the cfquery the query works 100% after it catches. Not sure why/how the sql script gets skipped/lags out.
# Posted By Oliver | 7/6/06 7:05 PM
I have the same problems with the combo box not always showing up. I even tried the cached within, but it still doesn't always work.

Any ideas?
# Posted By Steve | 9/19/06 7:57 AM
How can I create a column in a cfgrid with a combo box? I want to do this with query results from SQL Server and not a remote service?
# Posted By NleonWill | 2/12/08 5:29 PM

Calendar

Sun Mon Tue Wed Thu Fri Sat
     12
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31       

Subscribe

Enter your email address to subscribe to this blog.

Tags

actionscript ajax blogging cfsnippets coldfusion flash forms flex funny stuff misc model-glue off topic personal project learn slidesix sql

Recent Comments

Adding Auto Generated Code Downloads to BlogCFC
ada5fsa said: http://www.mountwashingto... http://extjs.com/forum/me... h... [More]

BlogCFC Survey #2
ada5fsa said: http://www.mountwashingto... http://extjs.com/forum/me... h... [More]

Most Difficult Captcha Of All Time
kokkooo said: [url=http://synchrophase.info/...]消費者金融 ブラック[/url] [url=http://geji-geji.com/]消費者金融ブラック[/url] [url=http... [More]

Most Difficult Captcha Of All Time
kokkooo said: <a href="http://synchrophase.info/...">消費者金融 ブラック</a> <a href="http://gej... [More]

Using A PlayStation 2 HDD In Your PC
Vodin said: Well dang. Thanks man, my uncle who owns a Video Game shop had a PS2 harddrive in the junk box, I sn... [More]

RSS


coldfusionbloggers

FullAsAGoog MXNA

Consumed By Feed-Squirrel.com