A while back I posted examples of using ColdFusion 8 Ajax support to power an
auto-suggest control and
related <CFSELECT> controls. Both examples required that the back-end CFC methods create arrays (1 dimension for the former, 2 dimensions for the latter). And I pointed out that I hoped we'd be able to tighten that syntax before we ship.
Well, we did. In the final CF8, the CFC method bound to auto-suggest can return a simple list (a string), and the CFC bound to a <CFSELECT> can return a query. This makes the code orders of magnitude simpler. I am not going to update those entries just yet (as these enhancements won't work with the public beta), but ...
The CFC method to power an auto-suggest could be simplified like this:
<!--- Lookup used for auto suggest --->
<cffunction name="lookupArt" access="remote" returntype="string">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var result="">
<!--- Do search --->
<cfquery datasource="#THIS.dsn#" name="result">
SELECT artname
FROM art
WHERE UCase(artname) LIKE Ucase('#ARGUMENTS.search#%')
ORDER BY artname
</cfquery>
<!--- And return it --->
<cfreturn ValueList(result.artname)>
</cffunction>
The CFC method to power a <CFSELECT> could now just return a query. And the <CFSELECT> control would then use the existing VALUE and DISPLAY attributes to specify the query columns to be used, like this:
<cfselect name="mediaid"
bind="cfc:art.getMedia()"
bindonload="true"
value="MediaID"
display="MediaType" />
These are great little enhancements, and I am glad the team was able to get them in just in time.
Thanks for the update.
--- Ben
--- Ben
An auto-suggest control is a text control, there is no separate id and value, what gets submitted is the text, just like any other <input type="text">.
--- Ben
error "exception thrown and not caught "
Thnx
I take it none of these CF Ajax tags work in CF 7 ?
Signed,
Trying to get the boss to upgrade...
--- Ben
Thanks
Great stuff. I'm loving the new CF8 features and your site is incredibly helpful in learning how to use them.
Is there any way I could talk you into giving an example (or mabey a future tutorial) on querying Exchange with the new cfexchange and cfexchangecontact tags to create an auto suggest box of someone’s email contacts?
Regards,
Scott
I just installed CF8 last week and I'm having trouble with the relatled select controls. My cfc return a query with two fields: rank & Product (value & display). The error I'm getting is: [Bind failed for select box a_proc, bind value is not a 2D array or valid serialized query]
CFC:
<cffunction name="lookupClarifyList" access="remote" returntype="query"
hint="Returns Clarify List given the list title">
<cfargument name="thisTitle" type="string" required="true">
<cfquery datasource="clarifySMST" name="getList">
SELECT e1.title as Product, e1.rank
FROM
table_hgbst_lst l1,
table_hgbst_show s1,
table_hgbst_elm e1,
mtm_hgbst_elm0_hgbst_show1 m1
WHERE l1.title LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="#thisTitle#">
AND s1.objid = l1.hgbst_lst2hgbst_show
AND s1.objid = m1.hgbst_show2hgbst_elm
AND e1.objid = m1.hgbst_elm2hgbst_show
AND e1.state != 'Inactive'
Order by RANK
</cfquery>
<cfdump var="#getlist#">
<cfreturn getList>
</cffunction>
CODE:
<cfform name="test" >
<select name="a_orig" required="yes">
<option value="Internal Document Source" selected>Internal</option>
<option value="3rd Party PP Product">External</option>
</select>
<cfselect name="a_proc" bind="docmgmt.pww.lookupClarifyList({a_orig})" bindonload="true"
value="rank" display="product"/>
</cfform>
--- Ben
I was able to call the cfc with CFInvoke and get the results. The reason the cfdump was there was if I used cfdebug in the url it shows the results of the click on an item in the first select box.
Since my post I have tried numerous changes and have even cut and pasted your examples from this blog and from the white paper an the Adobe site and I can't even get the ajax auto complete example to work.
I have checked that the CFIDE mappings in the CFAdmin is in place: C:\Inetpub\wwwroot\CFIDE and I have the same mappings in place in IIS.
I'm looking kind of foolish to my management as I told they how CF8 was going to make coding easier and faster and this is my third day trying to solve this ajax problem. My CF8 install was over CF7 and I didn't have any ajax code in place, but used CFC's extensively. I get the same results in IE6/7 and FF2.0. I had one of my CNYCFUG members try my code on his CF8 install and it worked. This seems to be a settings problem. Do you have any configuration points that I can check?
thanks, Jim
This is the outout from the cddebug window on my related select problem. If I understand this correctly it shows the cfc was called and the data was is being returned. It's just not loading it into the control. -- Jim
info:http: CFC invocation response: {"COLUMNS":["PRODUCT","RANK"],"DATA":[["Please Specify",0],["WinVisa",1],["ICVerify",2],["PcCharge",3],["Monetra",4],["Verifone",5],["Hypercom",6],["911 Payment",7],["Precidia",8],["DataCap",9]]}
info:http: HTTP GET /docmgmt/pww.cfc?method=lookupClarifyList&returnFormat=json&argumentCollection=%7B%22thisTitle%22%3A%223rd%20Party%20PP%20Product%22%7D&_cf_nodebug=true&_cf_nocache=true&_cf_clientid=84FA3E126422CA5AA58E6C7C0EBE96DD&_cf_rc=1
info:http: Invoking CFC: /docmgmt/pww.cfc , function: lookupClarifyList , arguments: {"thisTitle":"3rd Party PP Product"}
info:http: CFC invocation response: {"COLUMNS":["PRODUCT","RANK"],"DATA":[["SOW",0],["Quote",1],["Sales Order",2],["Addendum",3]]}
info:http: HTTP GET /docmgmt/pww.cfc?method=lookupClarifyList&returnFormat=json&argumentCollection=%7B%22thisTitle%22%3A%22Internal%20Document%20Source%22%7D&_cf_nodebug=true&_cf_nocache=true&_cf_clientid=84FA3E126422CA5AA58E6C7C0EBE96DD&_cf_rc=0
info:http: Invoking CFC: /docmgmt/pww.cfc , function: lookupClarifyList , arguments: {"thisTitle":"Internal Document Source"}
info:LogReader: LogReader initialized
info:global: Logger initialized
I know your a busy man but I really could use some direction. I cannot find any solution to the bind option not working in my CF8 install. Is this a bug? Does bind only work with certain doc type declarations?
Jim
It's driving me up the way - is this a bug in the ajax files?
A fix would really be appreciated.....
I got Ben's examples working on a local database the first time, so was curious about your problems.
If you look at your <cfselect ...> line, you will see that you missed the "cfc:" prefix in the bind= attribute. If I take the cfc: out of my code, I get that same error.
I don't know if you have gotten past this or not, but thought I would document for others searching "teh Internets".
I'm also getting the "exception thrown and not caught" javascript error message when I implement an autosuggest cfinput tag in my application.
If I have a clean standalone test, the autosuggest works great!
Anyone managed to get to the bottom of this yet?
Thanks.
ie: if it's a database of last names and you have an O'Donnel in there, it'll die.
Everythings been working a dream since I did that
Thanks for your suggestions Paul & Paul.
I have checked the data and there are no apostrophies coming back in the data and I haven't implemented an onRequestEnd.cfm file.
As I stated previously, a clean test version works correctly. However, upon further investigation, the clean version fails with the javascript exception error if the CFC file is not in the same directory as the CFM file.
My cfm page contains the following line, pointing to the cfc in a different directory:
<cfinput type="text" name="country" autosuggest="cfc:glenn.brilig.country.ajaxCountry({cfautosuggestvalue})">
My component code is:
<cfcomponent displayname="country" hint="Return information regarding countries">
<cffunction name="ajaxCountry" access="remote" output="true" returntype="array" returnformat="JSON" hint="For AJAX autocomplete of the country.">
<cfargument name="country" required="false" type="string" default="">
<cfset var result = ArrayNew(1)>
<cfquery name="getCountry" datasource="DSSOURCE" username="DSUSER" password="DSPASSWORD">
set nocount on
select description
from country
<cfif arguments.country neq "">
where description like '#arguments.country#%'
</cfif>
order by description
set nocount off
</cfquery>
<!--- Build result array --->
<cfloop query="getCountry">
<cfset ArrayAppend(result, getCountry.description)>
</cfloop>
<cfreturn result>
</cffunction>
</cfcomponent>
I have tried all suggestions from the other posters above, but I still get the Javascript error 'Exception thrown and not caught at line 787' when I try to bind a cfc in a <cfselect>. I found out that this line 787 is probably in c:\Inetpub\wwwroot\CFIDE\scripts\ajax\package\cfajax.js, but I don't know how to fix it.
What do I do wrong? Or is this a know bug and is there a fix for it?
@Jim: make sure the name of your cfselect is exactly the same as the value, otherwise you get the very misleading error 'Bind failed for select box a_proc, bind value is not a 2D array or valid serialized query'.
Rainer.
I do recall my post here above because I found the reason why I had the 'Exception thrown and not caught at line 787' error!
It turned out that our company has a rewrite in the httpd.ini which rewrites all '.cfc' to '.cfc?wsdl'. After removing this rewrite, all works fine for me.
Rainer.
RE: CFSELECT with cfc binding.
Either I'm doing something wrong or there is a bug in this functionality.
First, I can't get your example to work unless I remove the method onRequest from Application.cfc. With that method the cfc returns nothing. This is both by calling the cfc directly in the URL or through the CFSELECT bind= call.
Second, if I place the CFC in a directory that is mapped (ie not in the website root directory) I get the AJAX error Error invoking CFC NOT FOUND. For example I am calling the cfc: cacfc.database.school.getStates(). When I look at the source that coldfusion is generating it's looking for just /school.cfc. As soon as I move the cfc to a directory under the website root everything works fine.
The mapped directory problem is a known one, and I believe is to be addressed in the updater due out shortly.
The onRequest() issues sounds sounds like the same limitation with Web Services and more, and is documented as a restriction.
--- Ben
I have a local query tat returns two fields. When I run the cfselect like this ..
<cfselect name="Type"
bind="rsTypes"
value="typeid"
display="type"
bindonload="true" />
I get the following error...
Bind Failed .... bind value is not a 2D array or valid serialized query. It's got me stumped unhuh it does.
Chris
<cfform>
<table>
<tr>
<td>Select the Client</td>
<td><cfselect name="client_number"
bind="cm.getClient()"
value="client_number"
display="client_name"
bindonload="true">
</cfselect>
</td>
</tr>
<tr>
<td>Select the Matter</td>
<td><cfselect name="matter_number"
value="matter_number"
display="matter_name"
bind="cm.getMatter({client_number})">
</cfselect>
</td>
</tr>
</table>
</cfform>
<cfcomponent displayName="Client Matter" hint="cm" output="false">
<cfset THIS.dsn = "Monet">
<cffunction name="getClient" displayName="Get Client" hint="gc" access="remote" returnType="query">
<cfset var data = "">
<cfquery name = "data" datasource="#THIS.dsn#">
SELECT client_number,client_name
FROM dbo.client_matter
ORDER BY client_name
</cfquery>
<cfreturn data>
</cffunction>
<cffunction name="getMatter" displayName="Get Matter" hint="gm" access="remote" returnType="query">
<cfargument name="client_number" displayName="Client Number" hint="cn" type="string" required="true">
<cfset var data = "">
<cfquery name = "data" datasource="#THIS.dsn#">
SELECT matter_number,matter_name
FROM dbo.client_matter
WHERE client_number = #ARGUMENTS.client_number#
ORDER BY matter_name
</cfquery>
<cfreturn data>
</cffunction>
</cfcomponent>