Link to home
Start Free TrialLog in
Avatar of traport
traport

asked on

JQGrid and Coldfusion - Can't get display!

I can't for the life of me find what I'm doing wrong in this jqgrid. I've tried to break it down as simply as possible...

Here's my .cfm page:

<head>
<script>
application.cfstatic
		.include('scripts.js');
</script>
<title>Grid Test</title>
 <cfscript>
        param type="string" name="REQUEST.addScriptsHeader" default="";
        param type="string" name="REQUEST.addCSSHeader" default="";
        param type="string" name="REQUEST.addScriptsFooter" default="";
        param type="string" name="REQUEST.addCSSFooter" default="";
        param type="string" name="REQUEST.adder" default="";
        param type="string" name="REQUEST.scriptMinifier" default=".min";
        param type="boolean" name="REQUEST.jqGridLoaded" default=false;

    
        if(!REQUEST.jqGridLoaded){
            savecontent variable="VARIABLES.adder" {
                WriteOutput("<script type='text/javascript' src='/assets/scripts/_lib/jquery/plugins/loadmask-0.4/jquery.loadmask#REQUEST.scriptMinifier#.js'></script>
                    <script type='text/javascript' src='/assets/scripts/_lib/jquery/plugins/jqgrid-4.3.0/js/i18n/grid.locale-en.js'></script>
                    <script type='text/javascript' src='/assets/scripts/_lib/jquery/plugins/jqgrid-4.3.0/js/jquery.jqGrid#REQUEST.scriptMinifier#.js'></script>");
            }
            REQUEST.addScriptsHeader &= VARIABLES.adder;
            savecontent variable="VARIABLES.adder" {
                WriteOutput("<link href='/assets/scripts/_lib/jquery/plugins/loadmask-0.4/jquery.loadmask.css' type='text/css' rel='stylesheet' />
                    <link href='/assets/scripts/_lib/jquery/plugins/jqgrid-4.3.0/css/ui.jqgrid.css' type='text/css' rel='stylesheet' />");
            }
            REQUEST.addCSSFooter &= VARIABLES.adder;
            REQUEST.jqGridLoaded = true;
        }
</cfscript>
</head>

<body>
	<table id="list" class="scroll" cellpadding="0" cellspacing="0"></table>
 		<div id="pager" class="scroll" style="text-align:center;"></div> 
		<div id="mysearch"></div>
</body>

Open in new window


--- Here's my .cfc

<cfcomponent displayname="UserMgr" output="false"> 
  
<cffunction name="getTestUsers" access="remote" output="false" returnformat="json">
    <cfargument name="page" required="no" default="1">
    <cfargument name="rows" required="no" default="10">
    <cfargument name="sidx" required="no" default="">
    <cfargument name="sord" required="no" default="ASC">
    <cfset var q = "">
    <cfquery datasource="#session.currentdsn#" name="q">
    SELECT top 10 id, firstname, lastname
    FROM f_users
    <cfif len(arguments.sidx)>
    ORDER BY #arguments.sidx# #arguments.sord#
    </cfif>
    </cfquery>
    
    <cfreturn queryConvertForJQGRID(q, arguments.page, arguments.rows) />
  </cffunction>
    
  <cffunction name="queryConvertForJQGRID" access="package" returntype="struct" output="no"> 
    <cfargument name="q" type="query" required="yes"> 
    <cfargument name="page" type="numeric" required="no" default="1"> 
    <cfargument name="rows" type="numeric" required="no" default="10"> 
    <cfset var result = structnew()> 
    <cfset var rowStruct = structnew()> 
    <cfset var col = ""> 
    <cfset result.page = arguments.page> 
    <cfset result.total = ceiling(arguments.q.recordcount/arguments.rows)> 
    <cfset result.records = arguments.q.recordcount> 
    <cfset result.rows = arraynew(1)> 
    <cfoutput query="arguments.q" startrow="#(arguments.page-1)*arguments.rows+1#" maxrows="#arguments.rows#"> 
      <cfset rowStruct = structnew()> 
      <cfset rowStruct['id'] = id>
	  <cfset rowStruct['cell'] = arraynew(1)>
      <cfset rowStruct['cell'][1] = arguments.q['id'][currentrow]> 
      <cfset rowStruct['cell'][2] = arguments.q['firstname'][currentrow]> 
      <cfset rowStruct['cell'][3] = arguments.q['lastname'][currentrow]> 
      <cfset arrayappend(result.rows, rowStruct)> 
    </cfoutput>
	<cfset output = SerializeJSON(result)>
	<cfset output = replace(output,'.0','','all')>
	<cfset output = replace(output,'ROWS','rows','all')>
	<cfset output = replace(output,'PAGE','page','all')>
	<cfset output = replace(output,'TOTAL','total','all')>
	<cfset output = replace(output,'RECORDS','records','all')>
	<cfset output = replace(output,'CELL','cell','all')>
    <cfreturn output /> 
  </cffunction> 

</cfcomponent>

Open in new window


Here's my .js

$("document").ready(function() {

		jQuery("#list").jqGrid({
			url:'processor.cfc?method=getTestUsers',
			width:"auto",
			height:"auto",
			datatype: "json",
			colNames:['ContactID','First Name','Last Name'],
			colModel:[
				{name:'id',index:'id', width:55},
				{name:'firstname',index:'firstname', width:200},
				{name:'lastname',index:'lastname', width:250},
				
			],
			rowNum:10,
			rowList:[10,20,30],
			pager: '#pager',
			sortname: 'id',
			viewrecords: true,
			sortorder: "asc",
			caption:"User List"
			});

		});

Open in new window


I'm not getting a display on the front end and when I go to processor.cfc?method=getTestUsers I get:

The value returned from the queryConvertForJQGRID function is not of type struct.

If the component name is specified as a return type, it is possible that either a definition file for the component cannot be found or is not accessible.
 
The error occurred in C:/inetpub/wwwroot/tracitest/processor.cfc: line 17
15 :     </cfquery>
16 :    
17 :     <cfreturn queryConvertForJQGRID(q, arguments.page, arguments.rows) />
18 :   </cffunction>
19 :    

Ugh Please help!
ASKER CERTIFIED SOLUTION
Avatar of _agx_
_agx_
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of traport
traport

ASKER

Hey _agx_,

Thanks for the response. I don't know how to return the result variable versus the structure (and I guess I don't know how to return a structure, either).

What's the benefit to using array notation versus dot notation? Are you saying then case doesn't matter for javascript?

And (20 questions!)... Would you give an example of the VAR scope for output variables and if you could explain why that'd be much appreciated, too.

I'm a homegrown developer so it's people like you who really help me along. Thanks.
how to return the result variable

Inside your function, you're already creating a structure named "result". All you need to do is return that variable instead of "output":

  <cffunction ....>
      .... existing code
      <!--- return structure instead of "output" variable --->
      <cfreturn result />
  </cffunction>

What's the benefit to using array notation versus dot notation? Are you saying then case doesn't matter for javascript?


No, you were right the first time :) Javascript definitely *is* case sensitive.  That's the reason you need to use array notation. Unfortunately, when you use dot notation, CF ignores whatever case you used and converts everything to upper case:

         <cfset result.page = "something...">
        <!--- serialized as JSON ...  --->
        { PAGE="something..." }

... so your javascript won't work because it's looking for "page" (all lower case).  When you use array notation, CF sends the key name exactly as you entered it (ie all lower case)

         <cfset result["page"] = "something...">
        <!--- serialized as JSON ...  --->
        { page="something..." }



Would you give an example of the VAR scope for output variables and if you could explain why that'd be much appreciated, too.

Any variable used only within the function (ie function local variables) should be VAR scoped.  You're already doing that with the other variables here. Just do the same with "output" at the top of the function:

       <!--- use VAR to put these variables in the local scope --->
       <cfset var result = structnew()>
        ....
       <cfset var output = ""> 

VAR scoping is a complex topic, but an interesting one :) The reason you var scope is - thread safety. In other words, to prevent one thread from messing up the results of another thread. Usually you only encounter thread issues when you're storing components in a shared scope (like application).  That's not the case here ... but it's good to plan ahead and always make code thread safe from the get-go.

Here's a brief blurb about var scoping (or LOCAL-scoping in CF9+):
http://forta.com/blog/index.cfm/2009/6/21/The-New-ColdFusion-LOCAL-Scope

I'm a homegrown developer so it's people like you who really help me along.

Anytime. I always enjoy discussions on "how things work and why" :)
Avatar of traport

ASKER

Thank you. Very insightful answer & help. I'm going to put these things into practice.

For some reason <cfreturn result /> came back with an error Variable result is undefined on processor.cfc and nothing returned in the grid.
Hm.. that variable is clearly defined. Are you sure you put it in the right function - ie queryConvertForJQGRID?

<cffunction name="queryConvertForJQGRID" access="package" returntype="struct" output="no">
    <cfargument name="q" type="query" required="yes">
    <cfargument name="page" type="numeric" required="no" default="1">
    <cfargument name="rows" type="numeric" required="no" default="10">
   <cfset var result = structnew()>  <!--- **** DEFINED HERE --->
    <cfset var rowStruct = structnew()>
    <cfset var col = ""> 

    <cfset result["page"] = arguments.page>
    <cfset result["total"] = ceiling(arguments.q.recordcount/arguments.rows)>
    <cfset result["records"] = arguments.q.recordcount>
    <cfset result["rows"] = arraynew(1)>


    <cfoutput query="arguments.q" startrow="#(arguments.page-1)*arguments.rows+1#" maxrows="#arguments.rows#">
         <cfset rowStruct = structnew()>
         <cfset rowStruct['id'] = id>
       <cfset rowStruct['cell'] = arraynew(1)>
         <cfset rowStruct['cell'][1] = arguments.q['id'][currentrow]>
         <cfset rowStruct['cell'][2] = arguments.q['firstname'][currentrow]>
         <cfset rowStruct['cell'][3] = arguments.q['lastname'][currentrow]>
         <cfset arrayappend(result.rows, rowStruct)>
    </cfoutput>

   <cfreturn result />
  </cffunction>
Avatar of traport

ASKER

I'd incorrectly placed the cfreturn result in the function ABOVE.

Okay so that works to output on the processor.cfc?method=GetUsers page... Great!

Shows: "{"rows":[{"cell":[20,"Christian","Ready"],"id":20},{"cell":[21,"Sean","Louisin"],"id":21},{"cell":[22,"Mike","Coleman"],"id":22},{"cell":[23,"Jim","Studebaker"],"id":23},{"cell":[24,"",""],"id":24},{"cell":[29,"Yancy","Wharton"],"id":29},{"cell":[26,"Donald","Hawkins"],"id":26},{"cell":[30,"Scott","Harvey"],"id":30},{"cell":[31,"",""],"id":31},{"cell":[32,"Dana","Lecroy"],"id":32}],"page":1,"records":7289,"total":729.0}..."

Now, why doesn't that autopopulate a grid on the index.cfm page?
Not sure. I'll have to find a copy of jGrid and try it.  Do you see any errors in your javascript console (Firebug, etc..)?
Avatar of traport

ASKER

I think it's my min files. I'll take it from here. Really appreciate your help!
Avatar of traport

ASKER

The whole thread of input was awesome. Thanks so much.
Welcome :)