Our Blog

So you thought that onload would fix all of your problems. Say you wanted to select an item in the datagrid as soon as the form "loaded". Great, you may have though, I’ll use onload. If you did, you may have discovered that the form loads, and then the data loads, and most likely, when you run your onload function the data has not yet arrived. So how do you know when it does?

Some components (for some reason the tree doesn’t want to do it) trigger an event when their dataProvider changes. That event is called “modelChanged”. In order to be notified when that happens, add the following to your onload function:

var listener:Object = {};
      
listener.modelChanged = function(evt):Void {
   alert('Data loaded');
   <!--- do whatever you need to do when the data loads --->         
}

myGrid.addEventListener('modelChanged',listener);

This will work for datagrids and selects. To remove a listener that you no longer need:

myGrid.removeEventListener('modelChanged',listener);

I’ll show three different uses of this on a datagrid: selecting the first item when the data loads, clear the grid to use the filter shown in Filtering a grid as you type – using functions and load an empty grid and populate it with remoting instead.

Selecting the first item

<cfform name="myForm" format="flash" onload="onFormLoad()">
   <cfformitem type="script">
   <!--- onload function --->
   function onFormLoad(){
      var listener:Object = {};
      
      //put the controls in scope to avoid calling _root

      var contactList:mx.controls.DataGrid = contactList;
      
      listener.modelChanged = function(evt):Void {
         alert('Data loaded... select first item');
         <!--- remove listener, so that we are not longer notified of model changes --->
         contactList.removeEventListener('modelChanged',listener);
         <!--- select first item --->
         if (contactList.dataProvider.length){
            contactList.selectedIndex = 0;
         }
      }

      contactList.addEventListener('modelChanged',listener);
   }
   </cfformitem>
   <cfgrid name="contactList" query="contactsQuery" rowheaders="false">
      <cfgridcolumn name="name" header="Employee Name">
      <cfgridcolumn name="gender" header="Gender">
      <cfgridcolumn name="age" header="Age">
   </cfgrid>
</cfform>

Run the filter function

This is a slightly changed version of the applyFilter function. I also changed its name to better describe what it does now

<cfform name="myForm" format="flash" onload="onFormLoad()">
   <cfformitem type="script">
   <!--- onload function --->
   function onFormLoad(){
      var listener:Object = {};
      
      //put the controls in scope to avoid calling _root

      var contactList:mx.controls.DataGrid = contactList;
      
      listener.modelChanged = function(evt):Void {
         alert('Data loaded... clear datagrid until department is selected');
         <!--- remove listener, so that we are not longer notified of model changes --->
         contactList.removeEventListener('modelChanged',listener);
         <!--- empty search, should return no value --->
         search('',contactList,[]);         
      }
      listener.search = search;
      
      contactList.addEventListener('modelChanged',listener);
   }
   
   <!--- search function --->
      function search( term:String, grid:mx.controls.DataGrid, columns:Array ):Void {
      
         var filterTerm:String = term.toString().toLowerCase();
         
         if(_global.unfilteredData[grid.id] == undefined){
            if (_global.unfilteredData == undefined){
               _global.unfilteredData = {};
            }
            _global.unfilteredData[grid.id] = grid.dataProvider.slice(0);
         }
         
         if(filterTerm.length > 0) {      
            
            var filteredData:Array = [];
      
            for(var i = 0; i< _global.unfilteredData[grid.id].length; i++) {
               var item:Object = _global.unfilteredData[grid.id][i];
               var added:Boolean = false;
               
               for(var j = 0; j< columns.length; j++){
                   if(!added){
                     var value:String = item[columns[j]].toString().toLowerCase();
                     if(value.indexOf(filterTerm) != -1)   {
                        filteredData.push(item);
                        added = true;
                     }
                  }
                  else {
                     break;
                  }
               }
            }
      
         grid.dataProvider = filteredData;
      
         }
         else {
            grid.dataProvider = [];
         }
      }
   </cfformitem>
   <cfformgroup type="horizontal">
      
         <cfgrid name="departmentList" query="departmentsQuery" onchange="search(departmentList.selectedItem.id, contactList, ['department'])">
            <cfgridcolumn name="name" header="Department">
         </cfgrid>
         <cfgrid name="contactList" query="contactsQuery">
            <cfgridcolumn name="name" header="Employee Name">
            <cfgridcolumn name="gender" header="Gender">
            <cfgridcolumn name="age" header="Age">
         </cfgrid>
   </cfformgroup>

</cfform>

Load it with remoting

<cfform name="myform" height="250" width="400" format="Flash" timeout="300" onload="onFormLoad();">
<cfformitem type="script">
   function onFormLoad(){
      var listener:Object = {};
      
      //put the controls in scope to avoid calling _root

      var getData:Function = getData;      
      var contactList:mx.controls.DataGrid = contactList;
      
      listener.modelChanged = function(evt):Void {
         alert('Empty data loaded... calling remoting');
         <!--- remove listener, otherwise we will enter into an infinite loop --->
         contactList.removeEventListener('modelChanged',listener);
         getData();         
      }
            
      contactList.addEventListener('modelChanged',listener);
   }

   function getData():Void{
      <cfoutput>
      //create connection

      var connection:mx.remoting.Connection = mx.remoting.NetServices.createGatewayConnection( "http://#cgi.HTTP_HOST#/flashservices/gateway/");
      //declare service

      var myService:mx.remoting.NetServiceProxy;
      </cfoutput>
   
      var responseHandler:Object = {};
   
      //put the controls in scope to avoid calling _root

      var contactList:mx.controls.DataGrid = contactList;
      
      responseHandler.onResult = function( results: Object ):Void {
         //when results are back, populate the cfgrid
         contactList.dataProvider = results;
         mx.managers.CursorManager.removeBusyCursor();
      }
   
      responseHandler.onStatus = function( stat: Object ):Void {
         //if there is any error, show an alert
         alert("Error while calling cfc:" + stat.description);
         mx.managers.CursorManager.removeBusyCursor();
      }
      
      //get service, make sure you write the correct path
      myService = connection.getService("flashRemotingResponder", responseHandler );
      mx.managers.CursorManager.setBusyCursor();
      //make call

      myService.getMembers();
   }
</cfformitem>

   <cfgrid name="contactList">
      <cfgridcolumn name="name" header="Name" />
      <cfgridcolumn name="age" header="Age" />
      <cfgridcolumn name="gender" header="Gender" />
   </cfgrid>
</cfform>

Live example 1

Live example 2

Live example 3

Download the source

Laura

Laura

111 Comments

  1. Michael White
    Incredible stuff... you have a great understanding of how to apply that actionscript stuff... But how does one learn actionscript as it applied to coldfusion flash forms? any actionscript 2.0 book I've picked up so far has examples that use &quot;forbidden&quot; keywords. Do I just need an actionscript 1.0 book?
  2. Todd
    Wonder why this doesn't work:

    <cfformitem type="script">

    <!--- onload function --->
    function onFormLoad(){
    var listener:Object = {};
    var indexnum = '#url.indexnum#';
       
    //put the controls in scope to avoid calling _root
    var da_wkbk:mx.controls.DataGrid = da_wkbk;

    listener.modelChanged = function(evt):Void {
        alert(indexnum);
    <!--- remove listener, so that we are not longer notified of model changes --->
    da_wkbk.removeEventListener('modelChanged',listener);
    <!--- select item --->
    if (da_wkbk.dataProvider.length){
    da_wkbk.selectedIndex = indexnum;
        da_wkbk.vPosition = indexnum;
    }
    }

    da_wkbk.addEventListener('modelChanged',listener);
    }

    </cfformitem>

    I'm trying to dynamically select a grid row based on url.indexnum.

    If I hard code it like this it works:

    da_wkbk.selectedIndex = 50;
    da_wkbk.vPosition = 50;
  3. Todd,

    I haven't tested your code, but I first glance I notice you didn't assign a datatype to your indexnum variable. AS2.0 has strict datatyping so you probably need:

    var indexnum:Number = &lt;cfoutput&gt;#url.indexnum#&lt;/cfoutput&gt;;

    On a side note, beware of using CF variables in your AS functions. Every time the variable changes, CF recompiles the entire form before sending it to the user.

    Let us know if the change works.
  4. todd
    William - I figured it out - it was a complete ID10T error - The code works now but I get a weird problem - the grid is BLANK!! If i scroll up it reappears, but onload it's blank.
  5. Todd
    Update: My grid isn't blank anymore and the code works great. Don't know if anyone noticed a little gem in my code:

    grid.vPosition = indexnum;

    This will scroll the grid onload so that the selectedIndex is the top item in the grid (if the selectedIndex is not visible in the grid.


  6. disidiosus

    disidiosus

    Thanks for giving the modelChanged some press, it's a handy event. It also lead me to some much needed and very helpfull actionscript code in the Flex documentation. Guess I'd just never got that far before.

    One thing I used this for was to replace the simple bind on the label property of the base panel. I use the label to display record count info for a grid, but conditions around multiple binds in the label field was getting tricky with syntax.

    Finding modelChanged here, I changed to the modelChanged and cellPress events for the grid to populate a hidden textBox and bind the label to that.

    More complicated for a simple thing, but if you clear a grid and there is no longer a selectedItem or Index available, the label bind just says 'undefined'.

    Anyway, cheers!
  7. BM
    Hae you ever encountered two cfforms loading on top of one another? They are the same form but two instances load.

    This just started recently but I wonder if you've run into this problem. I wish I could provide a screenshot but this forum doesn't allow that. Nothing I have found in any documentation covers this, but I have noticed that it only occurs when I am running a template that uses &lt;cfpop&gt; ...
  8. Laura
    disidiosus,
    Your problem is probably more complex than this, but remember that you can use {(myGrid.selectedItem != undefined)?myGrid.selectedItem.myColumn:'any default'} for binding to remove the undefined.
    You can leave 'any default' blank '' if you don't want to show anything.

    BM,
    I've never seen that. But I don't see how cfpop would make any difference in the rendered html. Try using different names for your forms and see if it helps.
  9. Ville
    The code under "Selecting the first item" saved my day. Thank you!! :)
  10. Asher
    William,

    Could you clarify what you mean by...

    &quot;On a side note, beware of using CF variables in your AS functions. Every time the variable changes, CF recompiles the entire form before sending it to the user...&quot;

    And maybe give an example of how to better use CF variables in actionscript to avoid this issue.

    Thanks
  11. Laura
    Asher,
    Any ActionScript code we add to a cfform becomes part of the generated file. If anything in the generated file changes, then the form must be recompiled. Having a variable that changes in every request will make the form recompile each time, making the form slow to load, showing a blank screen (not the preloader).
    As a best practice, only have variables inside the controls, never in the ActionScript (unless it is a variable that never changes, such as a domain or script name)
  12. Asher
    Laura,

    Thanks for the direct answer... could you give an example of 'only having variable inside controls'
    I'm not sure what you mean by that...

    Thanks
  13. todd
    Asher:

    If I understand Laura correctly, she is saying that it is OK to use variables in a form item such as a text box.

    Ex. &lt;cfinput type=&quot;text&quot; name=&quot;#url.variable#&quot;&gt;

    Not in the actionscript - which would be like this:

    &lt;cfinput type=&quot;text&quot; name=&quot;textbox1&quot; onchange=&quot;var test = '#url.variable#'; if (test == &quot;testing&quot;){alert('test');}&quot;
  14. Laura
    Asher and Todd,
    Yes, that is what I meant. Except that todd's first example will also cause a recompile :(
    Variables should only go in the control's data place holder, most, if not all, of the other attributes will cause the source to change. If it is a text input, then the &quot;value&quot; can, and most likely will, be a variable, for textareas, the value inside the tags can be a variable, for grids and selects, the query's data can change every time and it would be fine. You get the idea.
    That also goes for &lt;cfif&gt; statements or loops that change what controls are included in the form or anything else that is not data.

    When in doubt, run your page and look at the source, you will find the name of the generated swf, something like 1913161393.mxml.cfswf then change the variable's value and refresh. If the number changes, then it was recompiled.
  15. todd
    Laura:

    I found a pretty cool way to use variables within my as that won't cause a recompile. It can only be used in certain scenarios though.

    On the main page of my site I set a shared object based on user selections. Than as the user navigates to a separate page, I reference that shared object to get the dynamic variable that I may use in a remoting call or whatever else I need to. It works pretty great!

    I have another question - If you could help I would greatly appreciate.

    I have a custom tag built to export a cfgrid to excel. It works perfectly - until and unless a grid row is selected. Once a grid row is selected, certain columns in that row simply disappear from my dataProvider - the weird thing is that it is only columns 1, 2, 3, &amp; 5 - cols 4, 6, &amp; 7 are fine.

    Any ideas???
  16. Anthony

    Anthony

    I'm trying to take this a bit further and having a problem. I've got data loading and everything fine. (great work on all the examples!) But what i'm having problems with is making items visible once a row is selected. I have a button who's label is bound to the selected cell and can make it visable. The problem is I have a cfformgroup type=panel that I want to make visable too. But it doesnt seam like you can give it a name. How can i target a panel from an AS function? I tried binding the visible property to selectedItem but couldn't get that to work.
  17. todd
    Anthony - check out the mxna reader post in this blog - that should give you some ideas on how to dynamically hide the panel.
  18. Neil Bailey

    Neil Bailey

    Anthony,

    I ran into this exact same problem a month or so back. Rather than making you feel the same pain, I'll just give you the answer without making you search for it.

    You have a panel:

    <cfFormGroup type="panel"....

    underneath that, have an invisible checkbox:

    <cfinput type="checkbox" name="chk_displayPanel" checked="no" visible="no" label="" />

    in the opening panel tag, place these attributes:

    <cfFormGroup type="panel" visible="{chk_displayPanel.selected ? true : false}" height="{chk_displayPanel.selected ? SOME_HEIGHT_HERE : -6}" label="SOME_LABEL_HERE" />

    notice the dynamic height tag; when you make a form element invisible, it just...goes away, but the space is still not available (you would just have a big empty white space where the panel used to be). However, by making the panel's height a negative 6, and then making it invisible, you have in essence made it disappear.

    What you would then do to make the panel appear/disappear is have a button with something like the following (anything with an onchange/onclick event would do the trick, I just happened to pick a button):

    <cfinput type="button" name="but_displayPanel" value="Display Panel" onClick="changePanelState();" />

    and, finally, have a function something like this:

    <cfFormItem type="script">
    function changePanelState():Void {
    if (_root.chk_displayPanel.selected) {
    _root.chk_displayPanel.selected = false;
    _root.but_displayPanel.label = "Display Panel";
    } else {
    _root.chk_displayPanel.selected = true;
    _root.but_displayPanel.label = "Hide Panel";
    }
    </cfFormItem>

    I am 100% positive that this can probably be condensed down some, but this is how I got it resolved. I use it all over the place now. If you have any problems, post something here and someone will be able to lend you a hand.
  19. Jason
    my session in the component was not defined when it is remoting.
    Is there any way that I can get my session?
  20. Jason
    Too sleepy i guess, CFC variable solved the problem. Sorry for the dumb question, got 2 more questions :p

    1) How can I re-populate after the datagrid loaded? Should I clear the datagrid first before re-populate thru the remoting?

    2) I'm trying to select the first item after it populated from the remoting. But I could not get it to work by just calling the onFormLoad().
  21. WayneG
    Dear Laura

    I would appreciate if you could help me with the following:

    I have been using a CFC to handle a grid update as per the shipped docs of CF7 from a flash form using a full submit, which then recompiles the flash form after submission. Its works fine. What i have now do is use actionscript and a facade to call a cfc to handle all calls and submissions via remoting.

    My question is that I don’t know the actionscript that handles a call via remoting to my facade. I currently create a object that then handles the variables to the function call via remoting for all other form submissions and selects calls.

    Have no idea how to handle grid updates etc in actionscript. Please you help me. I have an application which makes extensive use of grids, selects, text fields etc. The grids evade me.

    Kind Regards
  22. disidiosus

    disidiosus

    Reserved Words work around.

    Ok, it's getting near the end of my working week, so if anyone has time to test this further before Monday morning, and get back to confirm my initial tests, i'd be greatful. I haven't read this anywhere else yet, so my apologies if this has been covered.

    If you write your code in include files with the .as extension, you can freely use the reserved words. i.e. I have this code in a .as file, included onload, and it works perfectly!

    var myDate: Date = new Date();
    var date_str:String = (myDate.getDate()+&quot;/&quot;+(myDate.getMonth()+1)+&quot;/&quot;+myDate.getFullYear());
    alert(date_str);

    If this is used directly in the cfm you get the error. Also, this is within a function, so the code isn't being run straight away.

    Obviously the cf server isn't looking at all the code in the include file, and the flash player is happy to run it once it's compiled.

    My knowledge on how this works is limited, but if anyone else can test this and get back to me, much appreciated.
  23. Garry
    Just an aside from an old (51) Cold Fusion Programmer who started with 1.5 in Germany. I had a problem with the 32k limit yesterday and, not being a flash programmer, almost turned the project out the door. Then I started playing with two scripts I found here and VIOLA!!! the 32K limit is no longer a problem.

    We have an application that is a form group of tabs with each tab having n number of children. Also, the parents can be unlimited. That was the problem. After the second tab children grids loaded the 32k limit was reached.

    I am using the filter as you type function from this site and I did some reading on this functionality also and had a brain ****. So, I combined elements of the two scripts and now have a very unelegant solution that causes absolutely no hit against performance.

    Yes, feel free to tell me the code is a bit clunky. I have no problem with that not being a flash developer. But if it works for me maybe you'll get something out of it.

    Here is the code I use:

    First, the two functions rewritten from here:
    <cfsavecontent variable="onLoad1">
       Grid_Sales1.dataProvider.removeAll();
    </cfsavecontent variable="onLoad1">
    (with the number iterating through a loop that creates the grids)

    <cfsavecontent variable="binding1">
       {(trigger1.text != '') ? trigger1.dispatchEvent({type:'change'}) : 'init'}
    </cfsavecontent>
    (again, the functions are numbered with a loop that creates the affected grid)

    And the last form element in the group is:
    <cfinput type="text" enabled="yes" visitle="false" name="trigger8" value="init" onchange="#onLoad1#" bind="#binding1#">

    Used in conjunction with the filter as you type functionality it loads three main tabls with three children each with 300 or more records in each child grid.

    Yesterday, without this code, I could only load two of the main tabs with children before it died with the 32k limit error. Today, three main tabs with three children and 300 or more records in each child.

    Now, I'm NOT a flash programmer so don't hold me to this and please test for yourself. But I just thought I'd share with you since I've gotten a lot of help reading these posts.
  24. disidiosus

    disidiosus

    Reserved words workaround.

    Finished till Monday. So far I created a new Array object, and created a new date onject which I used to pass a date the the .selectableRange (which should only take a date object) successfully.

    var myDate: Date = new Date();
    myDate.setFullYear(2005, 12, 25);
    _root.leavingDate.selectableRange = {rangeStart: myDate};

    Happy Days... With the creation of objects and the apparent ability to write my own classes now... things a relooking up. (I haven't tried this with the updater yet, this was all done in a _global function held in a .as file called from the onload workaround.

    If anyone else trys this, let me know how you get on.
  25. elfrick

    elfrick

    Quick Q:

    How do you include a .as file at load time?


    2nd Q:

    I'm dynamically building the columsn in my data grid. I want some of them to format my numbers as currency, withthe currency symbol, 1000s seperators etc. Easy if I make the columsn in CF, but how do I do it from actionscript? Docs suggest building a cell renderer, but I suspect there is something already present in the Flex lib that I can use instead???




  26. disidiosus

    disidiosus

    To include a .as file:

    &lt;cfformitem type=&quot;script&quot;&gt;
    #include &quot;path/file.as&quot; (note, no ';' required.)
    &lt;/cfformitem&gt;
  27. WayneG
    Pls help...

    How do you submit datagrid changes via remtoing to a CF CFC? I dont know the action script or how to loop corectly to get the required column data that has been edited.

    I get it to work with a submitForm(), to CFC. Need flash remoting to do the work without having to build the flash form again...

    Pls help... thanx
  28. Michele

    Michele

    Has anyone figured out how to modify the first example for a cfselect? I would like to select the first option in my cfselect on form load, which will then trigger the grid to filter. Seems simple, but I can't get it to work. Thanks for any ideas.
  29. Laura
    Michele,
    for a cfselect, you only need to change this:
    var contactList:mx.controls.DataGrid = contactList;
    to this:
    var contactList:mx.controls.ComboBox = contactList;

    but really the cfselect always loads with the first item selected. If what you want is to run the filter after the data in the select/grid loads, you need to use the same code in the second example and change this:
    search('',contactList,[]);
    to the filter of your select, something like:
    search(mySelect.selectedItem.data,myGrid,['myColumnToFilterOn']);
    Remember to also add
    var mySelect:mx.controls.ComboBox = mySelect;

    You can maybe add the search code in both modelChanged functions (select and datagrid) in case they do not load at the same time.
  30. Michele

    Michele

    Thank you for the speedy reply, Laura. To be a bit more specific... I am trying to modify the example so that on load my grid is filtered based on an option in a cfselect (specifically to show active records, as opposed to inactive or all records). The confusing part (for me) is that my filter is saved in a cfsavecontent tag, not a function. So can I call that from within the onFormLoad function? Or do I need to convert my cfsavecontent tag to a function? Not that I know how to do that :-) I'm using the cfsavecontent because I was able to figure out how to modify it to first filter based on cfselect and then search in specific column - I just combined two of your examples. I could not figure out how to do this with the filter function. Here's my cfsavecontent:

    <cfsavecontent variable="filterGrid">
       if(_global.arrClinics == undefined) _global.arrClinics = clinicList.dataProvider.slice(0);
       
       var arrClinics = _global.arrClinics;
       var arrDisplay:Array = [];
       var fortext = forInput.text.toLowerCase();
       var selected = column.selectedItem.data;

       for(var i = 0; i < arrClinics.length; i++)
       {
          if(arrClinics[i].Status == status.value || status.value == 'All')
          {
             if(arrClinics[i][selected].toString().substr(0,fortext.length).toLowerCase() == fortext)
             {
             arrDisplay.push(arrClinics[i]);
             }
          }
       }
       clinicList.dataProvider = arrDisplay;
       recordCount.text = arrDisplay.length;
    </cfsavecontent>

    I think I could use your example with the filter function to show active records on load and then also use my cfsavecontent filter which is in the onchange of the cfselect and search input, but this doesn't seem as efficient as one filter function or cfsavecontent tag. I hope this makes sense. Thanks for all the great examples. I really appreciate your willingness to share your expertise.
  31. Jason
    Laura,
    How can I select the first item AFTER it done loading with remoting?
    Thanks
  32. Wayne G

    Wayne G

    Laura,

    Im struggling with a loop over an editable cfgrid that consists of 5 gridColums and at times up to 500 records plus. Two of the columns are set to boolean which can be checked or unckecked. I would like to only loop over the two boolean columns and then submit those columns to a update updateGrid=
    function(args:Object){
    // my code here to call make a remoting call to a facade.cfc
    }

    I just cant seem to get the loop to work, even if I try submit all the columns. The examples show editing and updating a grid on the clients side( eg: filtering etc.

    What is the actionscript code to to this please. I have been stuck for days now. Please help.

    I manage to update a grid with submitForm(); which the recompiles the submitted form to cfc. I just cant seem to get the code correct.

    Kind regards
  33. Fritz Dimmel
    Hi!
    I have a quite similar problem as one of my pre-posters.
    I want to filter my datagrid on things which are selected in some cfselects.
    It works find for all my select boxes and their onChange methods. But I want the datagrid to be filtered initially to not display all items and just the preselected one's.
    To filter you just have to call my funtion &quot;dgFilter()&quot;. But if I insert this function call in one of your examples above (onFormLoad function), this does not work, I'll always get unfiltered data.
    Anybody who can help me?

    Thanks,
    Fritz
  34. WayneG

    WayneG

    Fritz,

    Im not sure if this will be any help.But what you need to do is pass the dataprovider only the selected columns that you have filtered back to the grid. To do this you need to loop over the columns that you want. If you go to &quot;ColdFusion Flash Forms Macromedia Developer Center article&quot; all select cooments you will see I have posted a question relationg to remoting with actionscript that selects only the columns I want to pass as arguments to my cfc component. I have a gris with 6 columns but only select three of the 6.

    Hope this helps..

  35. Marco
    Hi,

    the filter casting a &quot;string&quot;, but it's mixed 1 with 13. How apply a exact, numeric filter?

    Thanks,
    Marco
  36. Marco
    I have resolved in this mode:

    if(value.indexOf(filterTerm) != -1)   {
       if(value == filterTerm) {
          filteredData.push(item);
          added = true;
       }
    }
    but the contactList grid is Virtual!.
    In fact if the selectmode is set to &quot;edit&quot;, no array returned on the form submit.

    Help me!

    Marco
  37. Neil Huyton
    Hi.

    Thanks for all your hard work with this incredible stuff.

    I have one question which I've been working on for the past 3 hours.

    I have followed your code for populating a grid using remoting when the form loads. However, I would also like to apply a filter as you type function to the grid. Everytime I try and filter it, all the data disappears from the grid. Sorry if this has been answered already - I've looked around for an answer, but my heads too frazzled now!!

    Thanks.
  38. todd
    Neil:

    Post your filtering code - it's probably something simple. Are you using toLowerCase()? Sometimes I forget to do that.

    Todd
  39. Laura
    Neil,
    When setting the data with remoting, use
    contactList.dataProvider = results.items;

    instead of
    contactList.dataProvider = results;

    That should solve your problem unless you try to use the filter before the data gets from the server.
  40. Neil Huyton

    Neil Huyton

    Todd, Laura... thanks for your help.

    Todd, I did have toLowerCase() in the code - I always used to forget that, so now i make a point of checking that first!

    Laura... that did the trick! How long have you been using actionscript? I need to download your brain!

    Thanks again both of you!
  41. Neil Huyton

    Neil Huyton

    Okay... so now I'm just being picky!
    How do I get it so that if I clear the search term field after filtering, all the original data repopulates the grid?

    Hopefully I'll figure it out before someone posts back. Also, as a side note, would it be possible to include comments in the search script fot this site?
    Lots of times I've read something in the comments, but can't remeber which post it was in so I've tried searching but that seems to only search the main post.

    Thanks.
  42. Melissa

    Melissa

    I have tried using
    <cfformitem type="script">
    #include "path/file.as" (note, no ';' required.)
    </cfformitem>
    as suggested above. But my flash form will not load. Is there something i may be missing?
  43. todd
    Try two things Melissa.

    One - paste the contents of your include where the include is and try to load that - you should get an error message if there is a prob with it.

    Two - are you inside of a cfoutput? If so, escape your # -

    ##include....blah
  44. Laura
    Neil,
    Change the last else from:
    grid.dataProvider = [];

    to:
    if(_global.unfilteredData[grid.id] != undefined) grid.dataProvider = _global.unfilteredData[grid.id];
  45. Melissa

    Melissa

    Todd,

    I did the two things you suggested. It is not located in a cfoutput tag. And when I paste the code from the as file to the cfform, the form loads. Can you have the onload function for a cfform in the as file?
  46. Michele

    Michele

    Neil,

    I'm also trying to populate a grid via remoting and then apply a filter to the grid data. How did you get this to work? My remoting work and the filter worked before I set up the remoting. I'm trying to call the filter function from the onResult function but I can't get it to work. Can you post your code where you call the function and display the results?

    Thanks!
  47. Michele

    Michele

    Neil,

    Please ignore my previous post. I figured it out. I had the right code in the wrong order!
  48. Neil Huyton

    Neil Huyton

    Hi.

    I'm struggling with calling a function from within a function. Basically, I insert some data into a database via remoting. On the result of that call, I then re-populate a grid so that the newly inserted data shows in that grid. I also need to refresh other grids in the form with the new data and so I have tried to call a function on that same result.

    I have tried setting the scope i.e.
    var getData = getData

    but still no luck.

    I noticed that the 'Load it with remoting' does the same thing i.e. calls the getData() function from within the onFormLoad() function, but I can't apply it to return calls from remoting.

    Any ideas?!!!!!

    Thanks.
  49. todd
    Neil:

    I've been successful with:

    myGrid.dataProvider = results.items;
    var getData:Function = getData;
    getData();

    Not sure if this will work in every scenario but it works where I need it to.
  50. Neil Huyton

    Neil Huyton

    Hi Todd.

    Thanks for your reply. I tried your code but it still doesn't work!
    Which scenarios have you found that this does and doesn't work?
    Could you possibly post your code where you use this... maybe I can rework what I've got to fit more in line with yours.

    Thanks for your help.
  51. Adam
    I'm trying to highlight rows based upon data values when the grid loads, but am having little luck. It seems as though the rows which are initally displayed by the grid format fine, but not those below. Any ideas?

    <cfset myQ = queryNew("col1,col2,checkCol")>
    <cfloop from="1" to="8" index="x">
    <cfset dummy = queryAddRow(myQ, 1)>
    <cfset dummy = querySetCell (myQ, "col1", x)>
    <cfset dummy = querySetCell (myQ, "col2", x*10)>
    <cfif (x mod 2) is 0>
    <cfset dummy = querySetCell (myQ, "checkCol", "Y")>
    <cfelse>
    <cfset dummy = querySetCell (myQ, "checkCol", "N")>
    </cfif>
    </cfloop>

    <cfoutput>
    <cfform name= "foo" format="Flash" action="test.cfm" timeout="1800"
    method="post" skin="haloSilver" width="625" height="425" onload="formOnLoad()">

    <cfformitem type="script">
    function formOnLoad(){
    // Color Rows as applicable based upon any issues found
    // Based on code found on http://www.asfusion.com/blog/
    var listener:Object = {};
    var myColor:Number = 0xB0C4DE;
    var i:Number = 0;

    var unattached:mx.controls.DataGrid = unattached;

    listener.modelChanged = function(evt):Void {
    <!--- remove listener, so that we are not longer notified of model changes --->
    unattached.removeEventListener('modelChanged',listener);

    <!--- Highlight items --->
    //make the loop with onEnterFrame instead of a "for"
    _root.onEnterFrame = function (){
    if(i < unattached.length) {
    //do one iteration of the loop
    if (unattached.getItemAt(i).checkCol == 'Y'){
    _root.updateColor(i,myColor);
    }

    i++;
    }
    else {
    //end the loop
    _root.onEnterFrame = undefined;
    }
    }

    //this is the function that does whatever we need in each iteration
    _root.updateColor = function (index,colorValue){
    //change the color of the edited row
    unattached.setPropertiesAt(index, {backgroundColor:colorValue});
    };
    }

    unattached.addEventListener('modelChanged',listener);
    };
    </cfformitem>

    <!--- Display Grid --->
    <cfgrid name="unattached" format="Flash" rowheaders="no" query="myQ" sort="yes" selectMode="edit" selectColor="##D2B48C">
    <cfgridcolumn width="100" name="col1" header="One" select="yes">
    <cfgridcolumn width="100" name="col2" header="Two" select="no">
    <cfgridcolumn width="100" name="checkCol" header="Y/N" select="no">
    </cfgrid>
    </cfform>

    </cfoutput>
  52. Neil Huyton

    Neil Huyton

    Hi Adam.

    I don't think you can select multiple items in a cfgrid.
  53. Neil Huyton

    Neil Huyton

    Sorry Adam.. just looked at your example again, you can select multiples....doh!!!
  54. Laura
    Adam,
    Your problem was a little more complex. But I have a solution. It was not that only the visible rows were updated but that the onEnterFrame was killed by some other component at a point so it couldn't finish the loop. What you will need to do is to put the onEnterFrame somewhere other than the root, in an empty movieclip:
    <!--- Highlight items --->
    //make the loop with onEnterFrame instead of a "for"
    var mcX = _root.createEmptyMovieClip("mcX",1000);
    mcX.i = 0;

       mcX.onEnterFrame = function (){
       if(i < unattached.length) {
             //do one iteration of the loop
             if (unattached.getItemAt(i).checkCol == 'Y'){
             _root.updateColor(i,myColor);
             }
       
          i++;
       }
       
       else {
          //end the loop
          mcX.onEnterFrame = undefined;
       }
    }
  55. Laura
    Neil,
    You can put the function in scope like todd showed you, it has to be *before* you declare the remoting function (onResult), just like we do for the controls (look at the post example code).
    There is a problem, however, if that function calls another one (it will never get called). So, in order to avoid all that, just call it with _root. In the post example it would be _root.getData(). I don't know if this is very elegant, but that's what I've been using to avoid problems when calling functions that call other functions.
  56. Neil Huyton

    Neil Huyton

    Hi Laura.

    Thanks for your help once again. At this stage elegance doesn't concern me, just as long as it works!!

    Thanks.
  57. Laura, thanks. That was a huge help to a project I'm working on. You rock!
  58. Joshua Buttler
    Hi guys,
    This one is driving me nuts. I have a cfform that I am pulling data into by invoking a CFC on the CFM page. I want the form to have styles applied to certain elements using the onload function and myFormElement.setStyle(yada, yada);. Now here is where I am newbie city. To translate CF recordset vars into actionscript I am taking a &quot;non&quot;-visible cfinput=text field and pulling #myRS.data# into that field and calling the value into actionscript (myText.text). The problem is, the value is not there during the onload function as you well know. I know there is a better way to do this. Help. :)

    Thanks!
  59. Laura
    Joshua,
    I don't think there is any easy way to know when the text input is populated...
    You could use one hidden input like this
    <cfinput type="hidden" bind="{(loadChecker.text.length>0)?alert('arrived'):'1'}" name="loadCheckerTrigger">
    <cfinput type="Text" value="some value" name="loadChecker">

    that checks when a regular input's value has been updated and then trigger a function that does what you need instead of the alert.
  60. Mike Kaminsky (ICF Consulting)

    Mike Kaminsky (ICF Consulting)

    I believe the reason why the cftree does not respond to the &quot;modelChanged&quot; event is because the cftree uses a different dataProvider than the one associated with the cfgrid and cfselect. The cftree dataProvider is based on XML and does not broadcast similar events.

  61. Maya
    Your cfgrid-onload-selectitem.cfm code is exactly what needed but I can not make it work.
    When trying to run your code I received the following message: Attribute validation error for tag CFFORMITEM. The value of the attribute TYPE, which is currently &quot;script&quot;, must be one of the values: HRULE,HTML,TEXT,VRULE,SPACER
    Are there some settings that need to be changed on the server? Windows 2000, CFMX7 JRun.

    Thanks





  62. todd
    maya - you need to run the cfmx 7.0.1 updater. cfformitem type=script was not introduced until then.
  63. Sean
    Thanks a lot for the tips, they're truly great, I feel slightly ahead of this slow moving product. BUT.. I'm having so much trouble getting an url variable into my flash form... I've included my code, works great, except I need it to auto-filter based on an url variable as well (I'm migrating from an old system), I figured I'd just use the data onload listener to simply rerun the filter function after the grid was loaded.. this looks fine, but it does not recognize the term.text variable that I have passed it, presumably because it hasnt arrived yet, it's driving me nuts... any ideas how I can get an url variable into the code without having to recompile the as everytime?


    <cfquery name="gettechnicians" datasource="#request.dsn#">
       select TechID,FirstName,LastName from technicians
    </cfquery>


    <cfparam name="url.something" default="Sean">


    <cfform name="TechnicianTool" onload="onFormLoad()" format="flash" width="500" height="400">


       <cfformitem type="script">
        function onFormLoad(){
           var listener:Object = {};

           //put the controls in scope to avoid calling _root
           var contactList:mx.controls.DataGrid = contactList;

           listener.modelChanged = function(evt):Void {
              alert('Data loaded... select first item');
              contactList.removeEventListener('modelChanged',listener);
              _root.applyFilter(term.text,contactList,['TechID','FirstName','LastName']);

           }

              listener.applyFilter = applyFilter;
           contactList.addEventListener('modelChanged',listener);
        }

          function applyFilter( term:String, grid:mx.controls.DataGrid, columns:Array ):Void {

             var filterTerm:String = term.toString().toLowerCase();

             if(filterTerm.length > 0) {
                if(_global.unfilteredData[grid.id] == undefined){
                   if (_global.unfilteredData == undefined){
                      _global.unfilteredData = {};
                   }
                   _global.unfilteredData[grid.id] = grid.dataProvider.slice(0);
                }

                var filteredData:Array = [];

                for(var i = 0; i< _global.unfilteredData[grid.id].length; i++) {
                   var item:Object = _global.unfilteredData[grid.id][i];
                   var added:Boolean = false;

                   for(var j = 0; j< columns.length; j++){
                       if(!added){
                         var value:String = item[columns[j]].toString().toLowerCase();
                         if(value.indexOf(filterTerm) != -1)   {
                            filteredData.push(item);
                            added = true;
                         }
                      }
                      else {
                         break;
                      }
                   }
                }

             grid.dataProvider = filteredData;

             }
             else {
                if(_global.unfilteredData[grid.id] != undefined) grid.dataProvider = _global.unfilteredData[grid.id];
             }
          }
       </cfformitem>

       <cfformgroup type="panel" label="Search Technicians">

          <cfformgroup type="horizontal">
             <cfinput type="text" name="term" width="120" value="#url.something#" onchange="applyFilter(term.text,contactList,['TechID','FirstName','LastName'])" label="Filter by:">
          </cfformgroup>

          <cfgrid name= "contactList" query="gettechnicians" height="200" rowheaders="false">
             <cfgridcolumn name="TechID" header="TechID">
             <cfgridcolumn name="FirstName" header="First Name">
             <cfgridcolumn name="LastName" header="Last Name">
          </cfgrid>

       </cfformgroup>

       <cfformgroup type="tabnavigator">
          <cfformgroup type="page" label="Add / Edit Properties">
              <cfformgroup type="horizontal" label="Your Name">
                <cfinput type="text" required="Yes" name="firstName" label="First" value="" width="100"/>
                <cfinput type="text" required="Yes" name="lastName" label="Last" value="" width="100"/>
              </cfformgroup>
          </cfformgroup>

          <cfformgroup type="page" label="Add / Edit Stuff">
              <cfformgroup type="horizontal" label="Your Address">
                <cfinput type="text" required="Yes" name="address" label="Address" value="" width="100"/>
                <cfinput type="text" required="Yes" name="city" label="City" value="" width="100"/>
              </cfformgroup>
          </cfformgroup>
       </cfformgroup>

    </cfform>
  64. Michael
    Disidious,

    I've been working with the exact code (the date formatter) you've listed above literally all day. I've tried every permutation of the syntax to no avail. I tried your recommendation to include the code (which I wrapped in a simple function) in an external 'as' file. It worked perfectly. It is beyond me why functions as elementary as getDate(), getMonth(), etc. are non-usable in a CFForm, but the workaround seems to have done the trick. Has anyone uncovered any drawbacks or latent flaws with using this method?

    On another note, are there any good references available for Flash Form development using CFForm? I'm getting tired of searching the entire internet everytime I hit a speed bump (although this site has been a goldmine of information).

    Thank You
  65. Michael
    Wow...Another great site. Thanks for the tip, Todd.

    Someone needs to cull all this information and write a book. I've always been a huge fan of one stop shopping.
  66. Thomary

    Thomary

    I have to wait for the 7.0.1 updater to be installed. I can not use the type=&quot;script&quot;.

    But I'm wondering if this will even help me...
    Because my query results are so big 20K records, the grid takes a long time to load.

    Would &quot;Run the filter function&quot; help with this. It sounds like the data still loads it just doesn't show until the selection is made?
  67. Thomary

    Thomary

    We added an onload function, which will select the first line in the grid.
    <cfformitem type="script">
    function onFormLoad()
    { data.selectedIndex = 0; }
    </cfformitem>

    BUT now my onChange function on the grid does not work.
    <cfgrid name="data" query="getArtists" height="160" width="510" rowheaders="false" onchange="{vensite.selectedIndex=0}{vendiv.selectedIndex=0}{status.selectedIndex=0}
    for(var i:Number = 0; i<vensite.length; i++)
    {if(vensite.getItemAt([i]).data==data.selectedItem.vsite)vensite.selectedIndex=i}
    for(var i:Number = 0; i<vendiv.length; i++)
    {if(vendiv.getItemAt([i]).data==data.selectedItem.vdivision)vendiv.selectedIndex=i}
       for(var i:Number = 0; i<status.length; i++)
    {if(status.getItemAt([i]).data==data.selectedItem.Status)status.selectedIndex=i}">

    I tried to move this code to the onload function but that did nothing to set the selection fields onload or onChange.
    These fields are sometimes null. Any help would really be appreciated.
  68. Joe Rebis
    Regarding the 32K issue (didn't know wehere else to place this comment) I had something interesting come up.

    I was using the following binding statement on most of my cfinput tags on a app using flash remoting. Works fine.

    bind=&quot;{(mygrid.selectedItem!=undefined)?mygrid.selectedItem.field1:''}&quot;

    Since I kept getting &quot;null&quot; responses in fields that had not been completed, I changed to this:

    bind=&quot;{(mygrid.selectedItem.length!=null)?mygrid.selectedItem.field1:''}&quot;

    This worked great for a few cfinputs. When I changed ALL cfinputs to match I threw the 32K error.

    So I stripped out TONS of extra action script code to see how far off I was but I still threw the error! I took out way more than was added.

    I am wondering why this happened. The only conclusion I can draw is that the 32K error does not just relate to the size (number of lines) of the app but also to the types of evaluations used. Thoughts?
  69. Daniel
    Todd,
    Way back when (third comment from the top) you wanted to pass a variable to contactList.selectedIndex = #your variable#
    You mentioned later that you got it working. What was your solution as I'm trying to do the exact same thing.

    Daniel
  70. todd
    i'm not positive, but i think i failed to pass the var i was expecting in the url. make sure your passing the var in (a cfparam never hurts) and make sure you're within a cfoutput.

    post your code and i'll see if i can help.

    don't forget to beware of the recompile though -
  71. Daniel
    Thanks Todd,
    But just the act of writing it down clarified my thinking. I didn't declare it as a variable within the script. I have it working well now with a session variable. BTW -- thanks for the heads up on vPosition as well

    Daniel
  72. Andy
    I am trying to filter a grid that is loaded by remoting. The grid loads, but when I start typing in the text field to filter the grid, nothing happens, but when you backspace out, the entire grid disappears. It reappears after you hit the space bar once. Below is my code... This is confusing...

    function onFormLoad(){
    var listener:Object = {};

    //put the controls in scope to avoid calling _root
    var getData:Function = getData;
    var search:Function = search;
    var patientGrid:mx.controls.DataGrid = patientGrid;

    listener.modelChanged = function(evt):Void
    {
    //alert('Data loaded... clear datagrid until department is selected');

    patientGrid.removeEventListener('modelChanged',listener);
    getData();
    search('',contactList,[]);
    }
    listener.search = search;

    patientGrid.addEventListener('modelChanged',listener);
    }


    function getData():Void
    {
       var connection:mx.remoting.Connection = mx.remoting.NetServices.createGatewayConnection( "http://chextdev.tch.harvard.edu/flashservices/gateway/";);
       
       var myService:mx.remoting.NetServiceProxy;
       
       var responseHandler:Object = {};
       
       var patientGrid:mx.controls.DataGrid = patientGrid;
       
       responseHandler.onResult = function( results: Object ):Void
       {
          patientGrid.dataProvider = results.items;
          mx.managers.CursorManager.removeBusyCursor();
       }
       
       responseHandler.onStatus = function( stat: Object ):Void
       {
          alert("Error while calling cfc:" + stat.description);
        mx.managers.CursorManager.removeBusyCursor();
       }
       
       myService = connection.getService("ppoc.patientGrid", responseHandler );
       mx.managers.CursorManager.setBusyCursor();
       myService.getDataSet();
    }
       
    private function editPatient():Void
    {
       getURL("editPatient.cfm?pat_id=" + patientGrid.selectedItem.PAT_ID);
    }

    private function newPatient():Void
    {
       getURL("addPatient.cfm");
    }

    private function newVisit():Void
    {
       getURL("addPatientVisit2.cfm?pat_id=" + patientGrid.selectedItem.PAT_ID);
    }

    private function viewPatient():Void
    {
       getURL("viewPatient.cfm?pat_id=" + patientGrid.selectedItem.PAT_ID);
    }
       
    function search( term:String, grid:mx.controls.DataGrid, columns:Array ):Void
    {
       var filterTerm:String = term.toString().toLowerCase();

       if(_global.unfilteredData[grid.id] == undefined)
       {
          if (_global.unfilteredData == undefined)
          {
          _global.unfilteredData = {};
          }
       _global.unfilteredData[grid.id] = grid.dataProvider.slice(0);
       }

       if(filterTerm.length > 0)
       {

          var filteredData:Array = [];

          for(var i = 0; i< _global.unfilteredData[grid.id].length; i++)
          {
             var item:Object = _global.unfilteredData[grid.id][i];
             var added:Boolean = false;

             for(var j = 0; j< columns.length; j++)
             {
                if(!added)
                {
                   var value:String = item[columns[j]].toString().toLowerCase();
                   if(value.indexOf(filterTerm) != -1)
                   {
                      filteredData.push(item);
                      added = true;
                   }
                }
                else
                {
                   break;
                }
             }
          }

          grid.dataProvider = filteredData;

       }
       else
       {
          if(_global.unfilteredData[grid.id] != undefined)
          {
             grid.dataProvider = _global.unfilteredData[grid.id];
          }
       }
    }
  73. Xavier
    How can I instruct actionscript to use a url or form scope variable? What I am trying to do is pre-select a row in the grid and display an error message posted after a server side validation. I am not using remoting.
  74. Laura
    Xavier,
    You cannot access them directly. You need to store the variables you are interested in in hidden fields. You will then reference them as myFormName.myHiddenField.
  75. Xavier
    Thank you, Laura. I tried but cannot get actionscript to pick up the form field. it just takes it as blank. The form field is there and if I hard code the form field value in the line
    if (myGrid.getItemAt(i)['myID'] == myFormName.myHiddenField){

    it does work and the row is selected.

    Here is my code:

    <cfif isDefined("form.toBeEditedID")>
       <cfinput type="hidden" name="myHiddenField" value="<cfoutput>#form.toBeEditedID#</cfoutput>">
    </cfif>

    function gridPreSelect() {
       var listener:Object = {};
       <!--- put the controls in scope to avoid calling _root --->
       var myGrid:mx.controls.DataGrid = myGrid;
       listener.modelChanged = function(evt):Void {
          <!--- remove listener, so that we are not longer notified of model changes --->
          myGrid.removeEventListener('modelChanged',listener);
          for (var i = 0; i < myGrid.dataProvider.length; i++){
             if (myGrid.getItemAt(i)['myID'] == myFormName.myHiddenField){
                myGrid.selectedIndex = i;
                break;
             }
          }
       }
       myGrid.addEventListener('modelChanged',listener);
    }
  76. xavier
    Laura,
    I wonder how I missed that. All it needed was pound signs around the form field and then have a cfoutput surround the <cfformitem tag. Thanks a bunch to you guys. Your site is a great resource!
  77. George
    I am trying to use example 2. I have a cfselect box and a cfgrid. I am using the applyFilter function from another example. I saw, and made the changes suggested in #30 above. So that the grid gets filled then emptied and then filled again with the first selection from the cfselect. Im not sure why it does not work. What could be wrong? I put the onLoad part in the form, changed the VAR statement and the search statement. What happens is that the alert pops up and thats it the grid gets filled with everything not just the items from the cfselect (first item in the cfselect). Im thinking that the applyFilter function may be stoping something. Any help would be great. Thanks
  78. Laura
    George,
    Why don't you use the search function in the example? I think you are passing a blank string or something like that so the applyFilter function thinks it should show you all records. I would check that you are referencing the dropdown correcly and passing the column to search for with the correct case (I think this is the most important thing to check)
    Almost always these problems are due to AS case-sensitivity issues.
  79. Lesley
    Todd,

    You mentioned that you have code to export data from a datagrid to excel. Can I get a copy? In my application, once the user has searched for his part, then he needs to export it. I am hoping your code will work.

    Thanks
    Lesley
  80. Lesley
    Can anyone explain to me why you would use "Remoting"? Is this a better way to retrieve data from a database?
  81. Laura
    Lesley,
    The example in the post is not a good use of Remoting because you would be manually doing what it already happens automatically. I added it because people wanted to see it anyway and there are specific cases when you can use it. There are many other cases when using Remoting is far better than submitting the form (which incurs in a page refresh). See this article http://www.adobe.com/devnet/coldfusion/articles/flashforms.html (you can see the application at http://www.asfusion.com/apps/realestate/ ) for a good use case of Remoting. Other examples are our MXNA reader (http://www.asfusion.com/mxna/ ) or the File Explorer (http://www.asfusion.com/projects/fileexplorer/ ) where you would not want the page to refresh every time you need new information to load.
  82. Michael

    Michael

    I wonder if there´s an event that fires when a TextField is filled with a value onLoad. It should be similar to the datagrid event but I couldn´t figure out yet.

    Does anyone have an idea?
  83. Kike
    Hi!

    The example in the post is great but i have a error when it load.

    The error is : "Flas Remoting Rsponder not found". I don't know why generate this error!

    Please Help me!!!!!
  84. Laura
    Kike,
    If you download the source and put it in your web root, you should not have any problem, otherwise, you will have to change the path to the CFC, FlashRemotingResponder (see the other posts on Remoting for more info on that)
  85. sam
    Hi all,

    How do we normally handle large data that is going to be loaded in the grid? I noticed that it may took sometimes before it gets loaded, especially when the flash form is starting and intializing.
  86. thomary

    thomary

    Good question Sam. I have two grids that are quite large. What I am looking into is doing something like the real estate app. Having the user select some criteria before the grid gets loaded. I just found that they put the gird up with no query. I haven't figured out the cfcomponent and cfargument yet but with the Real Estate Article "The Real Estate Sample Application – Part 1: (and 2) Building the Search Functionality with Flash Forms" at
    http://www.adobe.com/devnet/coldfusion/articles/flashforms.html,
    I feel I am going to be able to tackle it.
    Good luck to us both...
    HTH
  87. Justin

    Justin

    I have four related grids. When the user clicks on grid A, grid B is filtered, and when the user clicks on grid B, grid C is filtered and so on. What I am trying to figure out is how to make it such that when a person has something selected and they click "Save" (i.e. submit) the grids will reload with those items already selected for the user? I tried the example above (the first example) but I can't get it to work. The page reloads, but nothing is selected. Any help would be much appreciated.

    Thanks,
  88. George Lu

    George Lu

    Hi Laura,

    For your "Selecting the first item", can you select the item matching to an url variable? And when it's selected the item should be scrolled to the top so it's visible.

    George
  89. Prabhu Thomas

    Prabhu Thomas

    When using your code to select the first row in a grid, the row gets selected, but the onChange event of the grid is not fired.
    any help on how to invoke the onChange event of the grid when a row is selected thro code will be appreciated
  90. Tom L
    We have a data grid on our Intranet that pulls data from a SQL db when it loads. By that I mean I see the loading progress bar, then the CFForm (swf) loads on the page then it populates with the data.

    I am having a problem in Mac Opera _only_ where all I get is the CFForm default animated clock/watch but the data never arrives. All other browsers work fine. Do you have an example of this type of form on your site? A data grid that populates on load rather than requiring a button click/user interaction before a db call? I am just trying to see if it's us causing the problem, or if it's definately the browser.

    Anyone know about what might cause Opera to have an issue?

    Thanks much.
  91. Tom L
    Current nighly was the last one I tested - found here: http://my.opera.com/desktopteam/blog/

    but I believe the most current release has the issue as well. I can confirm when I get a chance to download it and install it.

    Thanks for the reply. I'd love to solve this.
  92. Laura
    Tom,
    I dont know what to tell you, I am running the last version and I haven't seen any issue. I've only seen problems in much older versions of Opera (on all OSs).
  93. Tom L
    OK. Are there any specific things that you can think of that might cause this? Again, it's only Mac Opera that this happens in. Is there a specific code block I can copy/paste for you? I am not the back-end CF guy, so I am not sure what you would need to see. The guys here don't care much about me and my Mac opera... :-)

    Thanks!
  94. Tom L
    I am running the current stable Opera now (Mac 9.02) with the latest Flash plugin (9.0.28.0) and am still having the problem. If you say you are NOT having the problem then it must be us - though all other browsers work for me, as does Win Opera 9.02. I have been able to get it to work in the past by downgrading to Flash 8 plugin, but I no longer can do this as we continue to develop Flash that needs the benefits of the latest version. I was suspecting Opera's Flash plugin implementation, but if it works for you then it must not be the browser. Any thoughts I can pass on to our CF guys would be appreciated. I like Opera! :-)
  95. Eric
    Does anyone know how to create a timer to refresh the data populated by remoting?
  96. prashant

    prashant

    Hi,
    I create a grid using cfgrid.
    i have to show currency symbol in price column
    "£" sign.
    For this i define this :
    <cfgridcolumn name="price" header="price" type="currency" mask="£" />

    but it does not show the pound sign.

    Any help appreciated.

    Thanks. in advance.
    Prashant
  97. Tad
    Laura,
    Perhaps you can shed some light on this? I am able to display data using remoting if I use a button as in your first example but no data will display in the onFormLoad function. Here's code I'm using for the onFormLoad function:

    <cfset qGetWR = queryNew("WR_SEQ, WRNUMBER, ADDENDUM, RESPONSE") />
    <cfform name="wrRecs" format="Flash" onload="onFormLoad():">
    <cfformitem type="script">
    function onFormLoad() {
    var listener:Object = {};
    var wrGrid:mx.controls.DataGrid = wrGrid;
    listener.modelChanged = function(evt):Void {
    alert('Empty Data Loaded, Calling Remoting');
    wrGrid.removeEventListener('modelChanged', listener);
    getData();
    }
    wrGrid.addEventListener('modelChanged',listener);
    }
    function getData():Void {
    var debug = mx.remoting.debug.NetDebug.initialize();
    <cfoutput>
    var connection:mx.remoting.Connection = mx.remoting.NetServices.createGatewayConnection("https://#cgi.HTTP_HOST#/flashservices/gateway/";);
    var myService:mx.remoting.NetServiceProxy;
    </cfoutput>
    var responsehandler:Object = {};
    var wrGrid:mx.controls.DataGrid = wrGrid;
    responseHandler.onResult = function( results: Object ):Void {
    wrGrid.dataProvider = results;
    mx.managers.CursorManager.removeBusyCursor();
    }
    responseHandler.onStatus = function (stat: Object ):Void {
    alert('Error: ' + stat.description);
    mx.managers.CursorManager.removeBusyCursor();
    }
    var qArguments:Object = {};
    <cfoutput>
    <!--- session vars set prior to this form --->
    qArguments.facility = '#session.facility#';
    qArguments.status = '#session.status#';
    </cfoutput>
    myService = connection.getService("wr.components.wrCompRemote", responseHandler)
    mx.managers.CursorManager.setBusyCursor();
    myService.GetWRIndex(qArguments);
    }
    <cfgrid name="wrGrid" height="550" rowheaders="no">
    <cfgridcolumn name="WR_SEQ" display="no" />
    <cfgridcolumn name="WRNUMBER" header="WR No." />
    <cfgridcolumn name="ADDENDUM" header="Addendum" />
    <cfgridcolumn name="RESPONSE" header="Response" />
    </cfgrid>

    This will work if I add a button with an onClick event and put the above code in a <cfsavecontent> tag but not with just a onFormLoad event. Any ideas?
  98. Tad
    Hi Laura & Nahuel,
    I've got the remoting working now, thanks for all of your postings, they are truly helpful. I've got a question for you and seek your advice/wisdom.
    Suppose our application has 10 or 12 maintenance tables, some of them containing only 10-20 records, others containing 400-500 or more. Each of the tables could have as few as 2-4 columns, others 5-10. I was looking at modeling it after the Real Estate application.
    Is there any advantage to creating a single Maintenance Table form with a drop down menu to select the table to be updated, inserted into, deleted from and then populating a preview grid and edit form? Can something like this be done with Flash Remoting? Would I run into issues with the 32MB sizing? I'd like to have a single form for maintenance tables but value your opinions prior to starting such a task. Any ideas? Have you attempted anything like this for any of your applications?
    Thanks for your support and any advice you can share.
  99. kll57
    Hi,
    I tried to post this earlier and got an error, so I apologize if this post shows up twice. I'm new to actionscript and flash remoting and find this site to be the most helpful. I currently have a cfform that looks similiar to the address application with the cfgrid on the left side that populates onload. I was using the code in this example to know when the cfform data arrives and it was working great. I then modified the cfform to start using flash remoting and set up my cfc's like the Real Estate app. including using the service facade .cfc. Now when I run the form the busy cursor just keeps running and the data grid never populates. I commented out the code for the listner.modelchanged function and grid populates sometimes. If it doesn't populate I have to keep hitting refresh and eventually the grid will populate. Is there a way to use the code to know when the cform data arrives using flash remoting? Thanks in advance for any help.
  100. thomary

    thomary

    I'm trying to get my cfselect fields to show on form load if the user is coming in from a link. (I send this link via email.) I have tried many version of
    for(var i:Number = 0; i<primesite.length; i++)
    {if(primesite.getItemAt([i]).data==data.selectedItem.primary_work_site)primesite.selectedIndex=i}

    within this code (posted below) but I can not get the cfselect fields populated. Any help or location of documentation would be greatly appreciated!!!!
    <cfif isdefined("url.back")>
    <cfformitem type="script" >   
    <!--- onload function --->
    function onFormLoad(){
    var listener:Object = {};
    var data:mx.controls.DataGrid = data;
          
    listener.modelChanged = function(evt):Void {
    alert('Data loaded... first item selected BUT none of the selection fields show the data.');
    <!--- remove listener, so that we are not longer notified of model changes --->
    data.removeEventListener('modelChanged',listener);
    <!--- select first item --->
    if (data.dataProvider.length){
    data.selectedIndex = 0;
           }
           }
    data.addEventListener('modelChanged',listener);
           }
    </cfformitem>

    <cfelse>

    <cfformitem type="script" >   
    <!--- onload function --->
    function onFormLoad(){
    data.selectedIndex = undefined;
    }
    </cfformitem>
    </cfif>
  101. John Keyston

    John Keyston

    The subject of this post is: "Knowing when the cfform data arrives". However, what if the data does not arrive? This was what was happening, intermittently, in my first CF project, just completed, which uses a couple of cfform onloads to populate grids using Flash remoting.

    After scratching my head for a while, I reasoned that it must take some time for the remoting service to become operational, and that I was perhaps trying to use the service before it was ready. In any event, when I added code to delay the call for data until I was in fact sure that remoting was operational, the problem of missing data disappeared.

    Since I did not know of any "event" or other way of determining the status of the remoting service, I added a remCheck function to my MemberService.cfc file. This function simply returns the value true if correctly executed:

       <cffunction
       name="remCheck"
       access="remote"
       returntype="boolean">
        <cfreturn true>
       </cffunction>

    If I could get the value of true returned from this function I would know that remoting was operational. So...

    Instead of calling a formOnLoad()function directly from <cfform onload="...">, I simply called a setUpRemoting function:

    <cfform onload="setUpRemoting()" ....>

    The last three lines of the setUpRemoting function are:

    function setUpRemoting()
    {
    ......      
    responseHandler.remCheck_Result =
    function(results:Boolean):Void
    {_global.remIsOn = results;}
    _global.MemberService =
    connection.getService(componentPath, responseHandler );
    _global.intervalId =
    setInterval(this, "checkRemoting", 100);
    }
    followed by:

    function checkRemoting(){
    _global.MemberService.remCheck();
    if (_global.remIsOn)
    {
    clearInterval(_global.intervalId);
    formOnLoad();
    }
    }

    formOnLoad{
    getdata();
    ........;
    ........;
    }

    So now, after requesting the remoting connection, the remCheck function is called remotely every 100msecs by setInterval/checkRemoting until remCheck returns a value of true. Then, and only then, is a call made to the formOnLoad function. So far, when using this code I never have a blank grid on loading. Before, I had them in one case only occasionally, but in another, most of the time.

    If anybody knows of a better solution to my problem, I would love to hear about it.


    John K
  102. tad
    John K:
    Can you post your complete setUpRemoting / onFormLoad code please? Might make it easier for some people to understand how you are accomplishing this. This same problem has been giving me a headache for quite some time....thanks for the insight.
  103. John Keyston

    John Keyston

    Tad,

    The script below is a simplified version of one that I am using. I have run it to make sure that nothing essential is missing. The default onResult response handler is not being used.

    <cfform onLoad="setUpRemoting()" etc.....>
    <cfgrid name="adminGrid" etc..... >
    <cfgridcolumn ... />
    <cfgridcolumn ... />
    <cfgridcolumn ... />
             ....
    </cfgrid>

    <cfformitem type="script">
    function setUpRemoting(){
    <cfoutput>
       var connection:mx.remoting.Connection = mx.remoting.NetServices.createGatewayConnection("http://#cgi.HTTP_HOST#/flashservices/gateway/";);
       var componentPath = "#request.componentPath#.services.MemberService";</cfoutput>
       var responseHandler:Object = {};
          
       responseHandler.onResult = function( results: String ):Void {
       mx.managers.CursorManager.removeBusyCursor();
       }      
                
       responseHandler.onStatus = function( stat: Object ):Void {
       alert("Error: " + stat.description);
       mx.managers.CursorManager.removeBusyCursor();
       }
                
       responseHandler.getAdminInfo_Result = function( results:String):Void
       {
       _root.adminGrid.dataProvider = results;
       mx.managers.CursorManager.removeBusyCursor();
       }
       <!---Check with Interval timer to determine when remoting is established--->
       responseHandler.remCheck_Result = function(results:Boolean):Void {_global.remIsOn = results;}
       _global.MemberService = connection.getService(componentPath, responseHandler );
       _global.intervalId = setInterval(this, "checkRemoting", 100);
    }

    function checkRemoting(){
       _global.MemberService.remCheck();
       if (_global.remIsOn)
       {
       <!--- Turn off Intervaltimer--->
       clearInterval(_global.intervalId);
       formOnLoad()
       }
    }
          
    function formOnLoad() {
       _global.MemberService.getAdminInfo();
    }
    </cfformitem>
    </cfform>

    My MemberService.cfc file includes:

       <cffunction
       name="getAdminInfo"
       access="remote"
       output="false"
       returntype="query">
          <cfquery name="getAllAdmin" datasource="#request.dns#">
             SELECT *
             FROM admin
          </cfquery>
          <cfreturn getAllAdmin>
       </cffunction>   



    I hope that gives you enough to go on.


    John......
  104. tad
    John,
    Thanks so much for this snippet of code, it works like a charm every time. I was sure the users wouldn't want to have to hit F5 to refresh the screen a number of times! :)