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:
--- Here's my .cfc
Here's my .js
I'm not getting a display on the front end and when I go to processor.cfc?method=getTe stUsers 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/tracite st/process or.cfc: line 17
15 : </cfquery>
16 :
17 : <cfreturn queryConvertForJQGRID(q, arguments.page, arguments.rows) />
18 : </cffunction>
19 :
Ugh Please help!
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>
--- 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>
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"
});
});
I'm not getting a display on the front end and when I go to processor.cfc?method=getTe
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/tracite
15 : </cfquery>
16 :
17 : <cfreturn queryConvertForJQGRID(q, arguments.page, arguments.rows) />
18 : </cffunction>
19 :
Ugh Please help!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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" :)
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" :)
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.
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.record count/argu ments.rows )>
<cfset result["records"] = arguments.q.recordcount>
<cfset result["rows"] = arraynew(1)>
<cfoutput query="arguments.q" startrow="#(arguments.page -1)*argume nts.rows+1 #" maxrows="#arguments.rows#" >
<cfset rowStruct = structnew()>
<cfset rowStruct['id'] = id>
<cfset rowStruct['cell'] = arraynew(1)>
<cfset rowStruct['cell'][1] = arguments.q['id'][currentr ow]>
<cfset rowStruct['cell'][2] = arguments.q['firstname'][c urrentrow] >
<cfset rowStruct['cell'][3] = arguments.q['lastname'][cu rrentrow]>
<cfset arrayappend(result.rows, rowStruct)>
</cfoutput>
<cfreturn result />
</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()> <!--- **** DEFINED HERE --->
<cfset var rowStruct = structnew()>
<cfset var col = "">
<cfset result["page"] = arguments.page>
<cfset result["total"] = ceiling(arguments.q.record
<cfset result["records"] = arguments.q.recordcount>
<cfset result["rows"] = arraynew(1)>
<cfoutput query="arguments.q" startrow="#(arguments.page
<cfset rowStruct = structnew()>
<cfset rowStruct['id'] = id>
<cfset rowStruct['cell'] = arraynew(1)>
<cfset rowStruct['cell'][1] = arguments.q['id'][currentr
<cfset rowStruct['cell'][2] = arguments.q['firstname'][c
<cfset rowStruct['cell'][3] = arguments.q['lastname'][cu
<cfset arrayappend(result.rows, rowStruct)>
</cfoutput>
<cfreturn result />
</cffunction>
ASKER
I'd incorrectly placed the cfreturn result in the function ABOVE.
Okay so that works to output on the processor.cfc?method=GetUs ers page... Great!
Shows: "{"rows":[{"cell":[20,"Chr istian","R eady"],"id ":20},{"ce ll":[21,"S ean","Loui sin"],"id" :21},{"cel l":[22,"Mi ke","Colem an"],"id": 22},{"cell ":[23,"Jim ","Studeba ker"],"id" :23},{"cel l":[24,"", ""],"id":2 4},{"cell" :[29,"Yanc y","Wharto n"],"id":2 9},{"cell" :[26,"Dona ld","Hawki ns"],"id": 26},{"cell ":[30,"Sco tt","Harve y"],"id":3 0},{"cell" :[31,"","" ],"id":31} ,{"cell":[ 32,"Dana", "Lecroy"], "id":32}], "page":1," records":7 289,"total ":729.0}.. ."
Now, why doesn't that autopopulate a grid on the index.cfm page?
Okay so that works to output on the processor.cfc?method=GetUs
Shows: "{"rows":[{"cell":[20,"Chr
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..)?
ASKER
I think it's my min files. I'll take it from here. Really appreciate your help!
ASKER
The whole thread of input was awesome. Thanks so much.
Welcome :)
ASKER
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.