CFGRID bind in HTML format does not work in Coldfusion 11 - coldfusion

OK, so I've spent the last couple of days researching this issue on various websites including this one and I'm still no closer to having an answer. I have seen claims that this was a bug and was fixed on Adobe's end in one of the CF11 patches and I have even seen one answer that claimed that Adobe was emailing the fix directly to individuals - though no information on how to go about getting Adobe to do that was provided on that webpage.
We just updated our intranet to Coldfusion 11 and pages that have a cfgrid using the HTML format and bind data from a cfc no longer show the cfgrid on the page. Other pages that use the Flash format with cfgrid (which apparently can't use the bind attribute with Flash) do work. These HTML cfgrid pages were working properly in Coldfusion 9 before we migrated to 11.
I have simplified the code as much as I can to eliminate other error possibilities - i.e. I've stripped out formatting and am pulling only a couple columns from the database. Here is the code I am currently working on in my dev sandbox:
<cfgrid format="html"
name="userGrid"
bind="cfc:editorFunc.getGridData({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})"
pagesize="20">
<cfgridcolumn name="REGION" header="Region">
<cfgridcolumn name="managmentArea" header="Management Area">
</cfgrid>
Here is the code in the cfc (the query does produce results when dumped to the page):
<cffunction name="getGridData" access="remote">
<cfargument name="page">
<cfargument name="pageSize">
<cfargument name="gridsortcolumn">
<cfargument name="gridsortdir">
<cfquery name="records" datasource="webData">
SELECT REGION, managmentArea
FROM areaDesc
ORDER BY Region ASC
</cfquery>
<cfset result = queryConvertForGrid(duplicate(records), arguments.page, arguments.pagesize)>
<cfreturn result>
</cffunction>
Has anyone had any luck getting a cfgrid like this to work in CF11? I could try a JQuery solution like JGrid, however I would prefer to figure out the existing issue with this code if possible.
Any help is much appreciated.

Add this..
<cfif not len(trim(arguments.gridsortcolumn))>
<cfset arguments.gridsortcolumn = "REGION">
<cfset arguments.gridsortdir = "desc">
</cfif>
query....
ORDER BY #arguments.gridsortcolumn# #arguments.gridsortdir#

Related

ColdFusion Component Not Returning Query

I have tried, off and on, for about 6 months or so to figure out CFC's but never could get it. So now I have SQL and LDAP queries scattered around in different pages that I would like to consolidate into a component. The query below works in it's own CF page, (I've omitted some of the query details for the post) but I'm getting a blank page instead of any results. This is my queries.cfc:
<cfcomponent>
<cffunction name="EmployeeQuery" access="public" returntype="query">
<cfargument name="EmployeeID" required="yes" type="string">
<cfldap action = "query"
name = "EmployeeAdd"
attributes = "distinguishedName, displayName"
filter = "sAMAccountName=#Arguments.EmployeeID#"
start = ""
scope="SUBTREE"
maxrows="1"
server = ""
username=""
password=""
separator=";" />
<cfreturn EmployeeAdd>
</cffunction>
</cfcomponent>
I've got a simple entry form where I enter text, click submit, and on the action page I have:
<cfif IsDefined("form.btnEmployeeAdd")>
<cfinvoke component="queries"
method="EmployeeQuery"
cfinvokeargument
name="EmployeeID"
value="#form.txtEmployeeID#">
<h3>Confirm Employee Entered</h3>
<cfoutput>#EmployeeAdd.displayName#</cfoutput>
</cfif>
My result is a blank page, I don't even get the h3 text. As mentioned, all this works fine in .cfm pages, but it craps the bed when I try to put it in a .cfc. As with all documentation on this, there's so many different ways to do this, but nothing I've tried works so I was hoping I could get a push in the right direction.
Your cfinvoke is missing a returnVariable
<cfinvoke component="queries" method="EmployeeQuery" returnVariable="EmployeeAdd">
<cfinvokeargument name="EmployeeID" value="#form.txtEmployeeID#">
</cfinvoke>
<h3>Confirm Employee Entered</h3>
<cfoutput>#EmployeeAdd.displayName#</cfoutput>
Alternatively if you're on CF10 or higher you could do this instead of your cfinvoke
<cfset employeeAdd = new queries().EmployeeQuery(form.txtEmployeeID)>
Looking at your code to invoke the cfc method, it seems like you are doing it in a wrong way. You have added cfinvokeargument inside cfinvoke as an attribute. cfinvokeargument should be added to cfinvoke body, instead. And as #matt suggested you need to add returnvariable attribute to cfinvoke in order to get results returned from the method. Like this.
<cfinvoke component="queries" method="EmployeeQuery" returnVariable="EmployeeAdd">
<cfinvokeargument name="EmployeeID" value="#form.txtEmployeeID#">
</cfinvoke>
Also as #matt suggested, if you are using cf10 or higher you can use new to instantiate the cfc and then call the method using . notation. Like this.
<cfset employeeAdd = new queries().EmployeeQuery(form.txtEmployeeID)>

ColdFusion 11 Data type preservation during serialization

I recently moved my code from CF9 to CF11 and I am having issues when I am trying to use serializeJSON. According to CF docs:
Starting from ColdFusion 11, the data type is preserved during the
code execution time for Query and CFCs.
SerializeJSON considers datatypes defined in the database for
serialization. If the database defines a column as a string, any
number inserted into the column will still be treated as a string by
SerializeJSON.
But I guess this is not the case....
When I am pulling data out of a varchar column in CF9 it comes out like this "docid":"123" which is what I want but in CF11 the same data look like this "docid":123 and is causing an issue with what I am trying to do.
To be more specific, my ids look like this 2001101009460111385185 which is longer than what javascript can accept and they get converted into scientific notation. With the old format I didn't have this issue because my ids were treated as a string which is what I want.
Note: my code is exactly the same on both versions of CF
Anyone had this issue before and HOW did you go around it?
Code Sample
I am calling this function via an AJAX call, this function returns an array with a struct in it. When I dump the return value after I serialize the result I can see a JSON object in my console but the quotes are missing from all the number values. In a test file I created a simple query and then I am serializing the results and everything looks good......
<cffunction name="locationData" returnformat="json" access="remote">
<cfargument name="locationid" required="yes" type="string">
<cfargument name="clientBrandid" required="yes" type="string">
<cfscript>
locationData = new mod_sigweb.components.xamplifierCFCs.location_info();
result = locationData.getLocation(locationid,clientBrandid);
</cfscript>
<cfdump var="#serializeJSON(result[1],'struct')#">
<cfabort>
<cfreturn #result#>
</cffunction>
The unfortunate workaround that I have had to use for this bug is to concatenate a space to the end of the value
<cfloop index="i" from="1" to="#ArrayLen(result)#">
<cfset result[i].docid = result[i].docid & " "/>
</cfloop>
and then the js has to be aware of this (I know, it's bad) and remove that trailing space.

File Not Found in CF11 even though file exists

Well, I have been experiencing same error as discussed here:
Coldfusion 10 File Not Found Error
I am using Coldfusion 11 , developer edition on my Laptop , Windows 8.1 Pro (OS).
People have suggested two approaches over there to overcome this problem:
1) Setting Missing Template in CFAdmin
2) Setup onMissingTemplate function in Application.cfc
I am basically not sure with any of the approaches , however, I would like to go with the first approach. Could anyone tell me how should I set up missing template in CFadmin?
Why do you prefer letting the server handle the missing template? Myself, I like to handle it on a per-application basis. Some applications should never have links leading to non-existing files, others may operate on that as part of its core.
Straight from adobe's docs, you can use (I accidentally pulled this info from cf8 docs, but the link is to current docs and the result is largely the same.
<cffunction name="onMissingTemplate" returnType="boolean">
<cfargument type="string" name="targetPage" required=true/>
...
<cfreturn BooleanValue />
</cffunction>
For a few of my projects, I've written a CMS (Content-Management-System) that stores all the content in the database in fashion.
CMSPages
------------
PID PTitle PFile PContent
1 Home /index.cfm <b>Hey!</b> Welcome to our gollygizmo website.
And then I (my real code actually uses cfincludes rather than directly in the document. You can do it either way, but it was easiest for me to demonstrate with inline code).
<cffunction name="onMissingTemplate" returnType="boolean">
<cfargument type="string" name="targetPage" required=true/>
<cftry>
<cfquery name="FindPage">
select * from CMSPages
where pFile = <cfqueryparam cfsqltype="nvarchar" value="#Arguments.targetPage#">
</cfquery>
<cfif FindPage.recordcount eq 1>
<cfoutput query="FindPage">show page stuffs</cfoutput>
<cfreturn true>
<cfelse>
<!--- Page not found, log some stuff or email stuff
include cgi data so you know where the link came from --->
Hey, this page doesn't exist, sorry about that.
<cfreturn true>
</cfif>
<cfcatch>
<!--- Something went wrong, log/email error info and --->
<cfreturn false>
<!--- We return false here to pass it back to the default error handler, which can be a handler set in cfadmin. --->
</cfcatch>
</cftry>
</cffunction>
In such a scenario, it's probably beneficial to cache queries based on query name, you can do something like
<cfquery name="local.FindPage#hash(arguments.targetpage)#" cachedWithin="...">
...
</cfquery>
<cfset request.FindPage=local["Findpage#hash(arguments.targetpage)#"]>
So that the queries are cached by unique names, even though it's easily accesible in your document by a common name.
However, if you still prefer server-centric missing template handling, a simple search for cold fusion admin missing template will bring you here.
In the ColdFusion Administrator, click on "Settings" to view the "Server Settings" page
Specify the absolute path that ColdFusion will use to find your error handling template

ColdFusion cfautosuggestvalue content is blank, even though a good array is returned from the cfc

I'm working with ColdFusion Server version 8,0,0,176276.
I'm trying to add an autosuggested form field, with asynchronous population through a cfc. I'm using http://www.forta.com/blog/index.cfm/2007/5/31/coldfusion-ajax-tutorial-1-autosuggest for inspiration and syntax.
The autosuggest field works fine if I use a static query (as in Forta's first example). The cfc is successfully returning an array when not used in the form field.
But when I use the cfc for autosuggest, there are no suggestions provided.
I can't see the contents of the input field with "view source," but if I do "inspect element" on the field in Chrome, I can see a div with class="yui-ac-bd" and a ul under it. The list items in the ul are empty when using the cfc, whereas when I use a static query, the list items contain the array members.
Here's the code on my page:
<cfform>
<cfinput type="text" name="JobP"
autosuggest="cfc:autosuggest.AutoSuggest({cfautosuggestvalue})">
</cfform>
And here's autosuggest.cfc:
<cfcomponent output="false" >
<cffunction name="AutoSuggest" access="remote" returntype="array">
<cfargument name="ObjectType" required="false" default="JOBP">
<cfset var result=ArrayNew(1)>
<cfquery name="Objects" datasource="UC4MP">
SELECT oh_name
FROM uc4.oh
WHERE oh_otype = '#ObjectType#'
AND oh_deleteflag = 0
AND oh_lastdate > sysdate - 90
AND oh_client = 1000
and oh_name like 'A%'
ORDER BY oh_name
</cfquery>
<cfloop query="Objects">
<cfset ArrayAppend(result,oh_name)>
</cfloop>
<cfreturn result>
If I put the following code on my page, it outputs the array with the desired contents:
<cfinvoke component="autosuggest" method="AutoSuggest" returnVariable="result">
cfdump var="#result#">
I don't use jQuery yet; most of my Google results for CF autosuggest have involved jQuery and I haven't been able to wade through them for relevance to my problem. Just in case that was going to be your suggestion.
Thank you all for your advice! I had not known there was a separate ajax debugger, the output of which immediately made the problem clear:
info:http: Invoking CFC: /rd/autosuggest.cfc , function: AutoSuggest ,
arguments: {"ObjectType":"A"}
My cfc arguments didn't include the autosuggest itself, so the string passed to the input field was being interpreted as "ObjectType" (the first argument) and used in the query. Since there are no records where oh_otype = 'A', the result was always empty.
I updated my cfc's arguments to
<cfargument name="ObjectType" required="yes" default="JOBP">
<cfargument name="autosuggest" required="yes">
and the invocation to
<cfinput type="text" name="JobP"
autosuggest="cfc:autosuggest.AutoSuggest('JOBP',{cfautosuggestvalue})">
...works perfectly now.
If i remember correctly when I did this some years ago, I had to create a virtual directory in Apacahe and set permisions using the following directives. You can apply the same to IIS if you are working in that environment. That should get it going for you.
Alias /CFIDE "/opt/coldfusion9/wwwroot/CFIDE"
<Directory "/opt/coldfusion9/wwwroot/CFIDE">
allow from all
Options FollowSymLinks
Since then I have been using the typehead javascript from bootstrap 2. Much cleaner and easier to style. You can still use your cfc to call the data and I am including the code to clean it up for typehead.
<cfinvoke component="autosuggest" method="AutoSuggest" returnVariable="result">
<cfset mylist = ArrayToList(result, ",")>
<cfset mylist=ValueList(ShowKey.keyword)>
<cfset mylist = jSStringFormat(#mylist#)>
<input name="keyword" id="keyword" type="text" data-provide="typeahead" data-items="10" data-source='["<cfoutput>#replace(mylist,',','","','ALL')#</cfoutput>"]'/>

CFSelect not binding but text box is

I am using CF10. I have a Select:
<cfselect name="company" id="company" query="qcompany" display="placename" value="placeid" queryposition="below">
<option value="0">--Select--
</cfselect>
I have another cfselect that is bound to the first:
<cfselect name="People" bind="cfc:schedule.GetPeopleArray({company})" ></cfselect>
I cannot get the second cfselect to display any results. To test whether or not I am receiving data from my component (which I will display at the bottom), I bound a text box:
<cfinput name="test" bind="cfc:schedule.GetPeopleArray({company})" bindonload="false"/>
This text box is displaying the results of the call to my component every time, but the cfselect never displays anything.
What could I possibly be doing wrong?
I have tried returning arrays and queries from my component. No help. I have tried adding display and value attributes to the second cfselect. No help.
Here is my component:
<cfcomponent output="false">
<cffunction name="GetPeopleArray" access="remote" returnType="array" output="false">
<cfargument name="company" type="string" >
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<cfquery name="qEmployee" datasource="texas" >
SELECT 0 as personid,'Select Person' as fullname,0 as sortorder
UNION
SELECT p.personid ,concat(firstname,' ',lastname) as fullname,3 as sortorder
FROM person p
INNER JOIN placeperson pp
ON p.personid=pp.personid
where personstatus='ACT'
and pp.placeid=#arguments.company#
order by sortorder,fullname
</cfquery>
<!--- Convert results to array --->
<cfloop index="i" from="1" to="#qEmployee.RecordCount#">
<cfset result[i][1]=qEmployee.personid[i]>
<cfset result[i][2]=qEmployee.fullname[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
</cfcomponent>
Ultimately, you may want use jQuery anyway, but FWIW your existing code worked fine with CF10. (The only change was removing the JOIN for simplicity) So either you are using different code, or there is something else going on we are unaware of ..
Truthfully the Ajax functionality does have some "quirks". However, you should not have any problem with a simple case like this. Aside from adding a text field, what other debugging or troubleshooting steps did you perform? What I usually recommend is:
Test the CFC independently first. Access it directly in your browser with a variety of sample values:
http://localhost/path/to/schedule.cfc?method=GetPeopleArray&company=someValue
I did this with the original code and discovered an error occurred when the company value is not numeric, like an empty string. (I suspect that might have been the problem) You can prevent that error by substituting an invalid ID like 0 instead. Note, be sure to use cfqueryparam to prevent sql injection.
AND pp.placeid = <cfqueryparam value="#val(arguments.company)#"
cfsqltype="cf_sql_integer">
Enable the CF AJAX debugger in the CF Administrator. Then append ?cfdebug to your test script so you can view the console and check for problems/errors.
http://localhost/path/to/yourTestForm.cfm?cfdebug
Again, I did this after tweaking the query. But there were no errors. Your existing cfform code worked perfectly.
Usually those two steps are enough to pinpoint any problems. If not, make sure your Application.cfc file (if you are using one) is not interfering with the Ajax request. That is a common gotcha. Test the code in a separate directory that is outside any Application files.
EDIT: Also, you may as well set bindonload="false" for the select list too. Since you do not want to call the function when the page first loads. Only when the user selects something from the list.