Ask a Jedi: ColdFusion Ajax example of retrieving fields of data (2)

Earlier today I blogged a simple example of using ColdFusion Ajax controls to load detail information based on a primary key. The reader who asked the question sent me a followup asking if it was possible to change the form to use a button instead of a keypress to load the data.

Using the second code sample from my previous entry, I added a button next to the ID field.

<cfform> id: <cfinput type="text" name="artid" id="artid"> <cfinput type="button" name="mybutton" value="Lookup"><br/> name: <cfinput type="text" name="artname" id="artname" readonly="true"><br/> description: <cftextarea name="description" id="description" readonly="true"></cftextarea><br/> price: <cfinput type="text" name="price" id="price" readonly="true"><br/> </cfform>

Now for the weird part. It's easy enough to bind to a button. I'd just use {mybutton@click}. However, I still need the ID value. So in order to bind to the CFC, I'd have to use:

<cfajaxproxy bind="cfc:test.getData({artid@none},{mybutton@click})" onsuccess="showData">

Unfortunately, this then requires that the getData method have a second argument. I could just add a dummy argument to the method, but that felt wrong. I decided to take another approach.

The cfajaxproxy tag allows you to bind to JavaScript functions as well. I switched my tag to the following:

<cfajaxproxy bind="javascript:getData({mybutton@click})">

Next, I knew I still needed a way to communicate to the CFC. I added another cfajaxproxy:

<cfajaxproxy cfc="test" jsclassname="dataproxy">

The next change was to add the getData function:

function getData() { var artid = ColdFusion.getElementValue("artid") if(isNaN(artid)) return dataService.getData(artid) }

I have to get the artid value manually so I made use of ColdFusion.getElmentValue. As before, I check for a valid number. Lastly I make use of dataService. What is that? I've added these two lines of JavaScript that make use of the new cfajaxproxy tag I added:

var dataService = new dataproxy() dataService.setCallbackHandler(showData)

Basically, dataService becomes a proxy to my remote methods in the CFC. This is probably a bit confusing now so let me paste in the entire template:

<cfajaxproxy bind="javascript:getData({mybutton@click})"> <cfajaxproxy cfc="test" jsclassname="dataproxy">

<script> function getData() { var artid = ColdFusion.getElementValue("artid") if(isNaN(artid)) return dataService.getData(artid) }

function showData(d) { //convert into a struct var data = {} for(var i=0; i < d.COLUMNS.length; i++) { data[d.COLUMNS[i]] = d.DATA[0][i] } document.getElementById('artname').value = data["ARTNAME"] document.getElementById('description').value = data["DESCRIPTION"] document.getElementById('price').value = data["PRICE"]

}

var dataService = new dataproxy() dataService.setCallbackHandler(showData) </script>

<cfform> id: <cfinput type="text" name="artid" id="artid"> <cfinput type="button" name="mybutton" value="Lookup"><br/> name: <cfinput type="text" name="artname" id="artname" readonly="true"><br/> description: <cftextarea name="description" id="description" readonly="true"></cftextarea><br/> price: <cfinput type="text" name="price" id="price" readonly="true"><br/> </cfform>

I hope this helps and shows yet another variation on the theme from earlier today.

Archived Comments

Comment 1 by Dave posted on 10/20/2009 at 6:37 PM

How would you add a "Clear" button?

Comment 2 by Raymond Camden posted on 10/20/2009 at 8:05 PM

I'm working on a part 3 for the original questioner, I'll try to get that in as well.

Comment 3 by Matt posted on 4/27/2011 at 1:18 PM

Hello Raymond, I recently applied the CF9 9.0.1 patch to our servers and now have an error when using the above solution. the error returns a WDDX packet parse errorat line 1 column 1. Content is not allowed in prolog. I have looked up this error and it seems to point to the way the data is being returned. Have you come across the same issue with using this example on CFP version 9.0.1.
Thanks
Matt

Comment 4 by Raymond Camden posted on 4/27/2011 at 3:28 PM

When you use Firebug, or Chrome Dev Tools, what does the Ajax response look like?

Comment 5 by Matt posted on 4/27/2011 at 4:42 PM

Hi Ray, i'm using Firebug and i don't really see anything that resembles the Ajax response. The code just looks like the Standard CF error html. I have expnaded the Ajax error line in the console and looked on the response tab and see the standard CF error html output.

Comment 6 by Raymond Camden posted on 4/27/2011 at 5:35 PM

You don't see _any_ Ajax response? There is definitely one there. Is this online where I can see?

Comment 7 by Frijoles_Jr posted on 8/3/2011 at 6:00 PM

Hi Ray,
I can shed a little bit of light on Matt's issue: The difference between 9.00 and 9.01 that breaks the cfc invocation when using a local cfc with access="remote", is the substitution of quotes for curly braces. I've made a cfc available online on a dev server to illustrate the difference - let me know if you need to see it in it's page context or it is otherwise unavailable, I've just dropped our usual directory security on the cfc.

Works (the 9.0 version):
http://128.83.148.234/bookshopdoor/captcha.cfc?method=createCaptcha&returnFormat=json&argumentCollection=%7B%7D&_cf_nodebug=true&_cf_nocache=true&_cf_rc=0

Doesn't work:
http://128.83.148.234/bookshopdoor/captcha.cfc?method=createCaptcha&returnFormat=json&argumentCollection=%22%22&_cf_nodebug=true&_cf_nocache=true&_cf_rc=1

Comment 8 by Raymond Camden posted on 8/5/2011 at 2:43 PM

So are you running the same code as me then? The request is what's bad - as you said.

Comment 9 by Frijoles_Jr posted on 8/5/2011 at 3:58 PM

I don't know what all you're running, but the dev server where the request is bad is running Standard Edition 9.0.1 in a Windows Server 2003/IIS6 environment, and the production server where the same code works is running Standard Edition 9.0.0 in a Windows Server 2008/IIS7 environment. I've experienced the same issue with and without cfAjax on the page, and am not using any js libraries that don't come with CF out of the box.

The funny thing about this is the same function works in 9.0.1 when invoked on load, via &lt;cfset foo=CreateObject("component","captcha").createCaptcha()&gt;
but it fails in 9.0.1 when invoked via a JS function, like so:
&lt;cfajaxproxy cfc="captcha" jclassname="cfimageCaptcha"&gt;
&lt;script language="Javascript"&gt;
var refreshCaptcha = function() {
var jsCaptcha = new cfimageCaptcha();
jsCaptcha.setCallbackHandler(populateCaptcha);
jsCaptcha.createCaptcha();
}
&lt;/script&gt;

Spark any ideas?

Comment 10 by Raymond Camden posted on 8/7/2011 at 6:14 PM

Not off hand - if you can share _all_ the code via pastebin, and if I can hit it remotely to test, I can try. Or - if you can make a small folder that demonstrates that issue and email me that folder so I can run it here, I can try that too.

Comment 11 by Richard Cook posted on 8/13/2011 at 8:33 PM

We just upgraded our dev server and getting the same issue. Any updates on this? Ray, if you need to get in, I can get you into our site.

Comment 12 by Raymond Camden posted on 8/13/2011 at 8:33 PM

This would normally be a paid engagement for me, but if you want to ping me via email I can take a quick look.

Comment 13 by Ted Johnson posted on 10/20/2011 at 2:16 AM

Anyone find a solution? Same problem... code was working perfectly with 9.0 and this error on 9.01. Just a simple AJAX call to a CFC. I guess I need to figure out how to downgrade to 9.0 if AJAX is broken with 9.01.

Comment 14 by Raymond Camden posted on 10/20/2011 at 5:51 AM

What do you see with Firebug or Chrome Dev Tools?

Comment 15 by Ted Johnson posted on 10/20/2011 at 8:26 AM

I ended up reverting to CF 9.0 which fixed the problem and AJAX is now working again. I will try and set up a simple AJAX test on a CF 9.01 server so I can reproduce the error. It was a very simple call to a CFC and like Frijoles said, the issue is CF 9.01 is using the wrong characters to escape quotes. Look at his examples... one is the way 9.0 escapes it, and the other is the way 9.01 does it. Those are generated by the coldfusion AJAX built it stuff.

Comment 16 by AH posted on 3/21/2012 at 9:36 PM

Hi,

We are having the same issue of CF 9.0.1 breaking the CF Ajax Tag.

Is there any solution for this issue?

Comment 17 by Ted Johnson posted on 3/21/2012 at 10:38 PM

No solution found by me yet. Either you have to revert to CF 9.0 or stop using CFAJAX. On one site, I started using the JQuery AJAX and that works fine.

Comment 18 by AH posted on 3/22/2012 at 4:47 PM

Thanks Ted for your response. Can you please show code sample of how to call JQuery and AJAX?

Thanks.

Comment 19 by Matt posted on 3/22/2012 at 5:21 PM
Comment 20 by Steve Hammonds posted on 9/13/2012 at 9:52 PM

We are having the same problem after upgrading to CF 9.0.1. Clearing the user's temporary internet cache makes the problem go away. I theorized that the user was loading all the Ajax JS generated by 9.0 from cache from a previous visit. But, I am unable to resolve the problem by forcing refresh of the page by using no cache headers. I also turned off Caching on the CFIDE folder in IIS and it still doesn't fix the problem. Short of getting every user to empty their cache I can't find a workable solution. It's been going on for several weeks now, maybe I am barking up the wrong tree. I KNOW deleting temporary internet files works. Just not sure why.

Comment 21 by Raymond Camden posted on 9/13/2012 at 10:05 PM

@Steve: The same problem as who? I don't believe the earlier commenters said anything cache related.

Comment 22 by Steve posted on 9/13/2012 at 10:09 PM

Same problem as Matt, Ted, Ah. Ajax calls not working after updating to 9.0.1. We get the error "WDDX packet parse error at line 1 column 1. Content is not allowed in prolog" in the exception log.

No one else mentioned cache problems, but I have found that having the client delete their temporary internet files fixes the issue. I just need a better solution that can be applied server side.

Comment 23 by Raymond Camden posted on 9/13/2012 at 10:12 PM

WDDX parse seems to imply it isn't using returnformat=json. I believe I asked this with others but didn't get a response - but can you put your demo online so I can run a test?

Comment 24 by Steve posted on 9/13/2012 at 11:41 PM

I am behind a firewall here. It is impossible to duplicate because I think the client must have previously visted the old page (CF 9.0 version) and cached the results. I can't duplicate it myself, but I have clients still getting the error. I'm going to have to find a client getting the error and debug on their machine.

I don't really expect you to try to solve this, I just hoped you were aware of a solution from the previous posts. I am going to post this in case it helps someone else.

One thing I've noted. The failed ajax calls are actually a cfajaxproxy invocation of a cfc method. When you use CFAjaxproxy you get some javascript generated on the page:

ColdFusion.AjaxProxy.invoke(this, "incHitCount","6F6FA08F87A09D12A9C38D", {photoid:photoid});

The call that works (after deleting temp internet files) passes these parameters:
_cf_ajaxproxytoken 6F6FA08F87A09D12A9C38D
_cf_clientid D91FD3EB7398C1AA0521AAB6E57A2BC8
_cf_nocache true
_cf_nodebug true
_cf_rc 5
argumentCollection {"photoid":"20588"}
method incHitCount
returnFormat json

The failed call passes these url parameters:
_cf_clientid 1EB45B4DD5168A7956A672D132B3609A
_cf_nocache true
_cf_nodebug true
_cf_rc 0
argumentCollection "71CF9B238E96AB51A1D9C7"
method incHitCount
returnFormat json

So my theory is that the client has cached the javascript that was generated by CFAjaxproxy for CF9 and the arguments generated don't work for the new version because they are in a different order or have different parameters.

Based on this I thought adding the proper headers would force a reload of the page and fix the problem, but for some reason it didn't. If I find the answer I'll post it.

Comment 25 by Ted Johnson posted on 9/13/2012 at 11:45 PM

I don't think the issue here is old JS being cached. Sadly, the only real solution to this problem is to not use CFAJAX. I've switched to the JQuery AJAX solution instead. Very frustrating that it simply doesn't work, especially since it worked fine with the previous version.

Comment 26 by Raymond Camden posted on 9/14/2012 at 12:17 AM

@Steve: Truly weird. You would think you could use IIS or Apache settings though to set a no-cache header for those directories. Would that work?

@Ted: I don't think it is fair to say it doesn't work. It does work. The issue is older JS files being cached in the user's machines. This will not be a universal problem at all, but only impact those with cached copies of the files. I believe checking with the web server to reset the cache is a possible solution.

Comment 27 by Steve posted on 9/14/2012 at 12:33 AM

Either that or I am just wrong. I'll take another look. Maybe I screwed something up the first time.

Comment 28 by frijoles_jr posted on 9/15/2012 at 12:23 AM

I noticed the recent activity on this thread and thought I would give an update and solution that worked for me, for the benefit of Matt and Ted (Steve seems to be experiencing a different issue, since the the cache wasn't relevant to the issue I was experiencing.

After stepping through the issue I found that the root cause was an extra parameter in the script generated for the AjaxProxy invoke function:

var _cf_captcha=ColdFusion.AjaxProxy.init('/includes/captcha.cfc','cfimageCaptcha');
_cf_captcha.prototype.createCaptcha=function(id) { return ColdFusion.AjaxProxy.invoke(this, "createCaptcha","", {id:id});};

versus the 9.0 version which works,

var _cf_captcha=ColdFusion.AjaxProxy.init('/includes/captcha.cfc','cfimageCaptcha');
_cf_captcha.prototype.createCaptcha=function(id) { return ColdFusion.AjaxProxy.invoke(this, "createCaptcha", {id:id});};

This shifted the content of the _45e variable in cfajax.js over to _45f, resulting in an error.

So I did a bit of googling over extra arguments in the cfajaxproxy invoke, and turned up the following at Andy Scott's site:

http://www.andyscott.id.au/...

His solution solved my issue , and if there are consequences, I haven't paid them yet, so consider it a good fix. Your mileage may vary

Comment 29 by Steve posted on 9/15/2012 at 12:30 AM

I found Andy's blog entry as well. That's what pointed me in the direction of cached versions of cfajax.js.

I think I can report that my problem has been resolved by telling IIS not to cache JS files in the /CFIDE/scripts/ajax/package folder. Since I made that change this morning there have been no further errors logged.

Comment 30 by John posted on 10/11/2012 at 5:13 PM

I'm getting the same "WDDX packet parse error" on CF 9.0.1 but the cfajax works on CF 9.0. It appears that the argumemtCollection is getting encoded (viewed via firebug), but I haven't found a work around.

Comment 31 by Raymond Camden posted on 10/11/2012 at 6:28 PM

Best I can recommend is switching to a pure jQuery solution instead. You can also open a tech support request too.

Comment 32 by albert posted on 10/15/2012 at 4:21 PM

I'm using this function to take data from grid column,
but I have javascript error if grid column value is null

function showWorkloadForm(){
var wldID = ColdFusion.getElementValue("workloadGrid","workloadGridForm","SCRN_NUM");
//alert(wldID);
var CTG = ColdFusion.getElementValue("workloadGrid","workloadGridForm","CTG");
var TFI = ColdFusion.getElementValue("workloadGrid","workloadGridForm","TFI");
/*var PPEND = ColdFusion.getElementValue("workloadGrid","workloadGridForm","PPEND");
if(PPEND == null){
alert("PPEND NULL");
}
alert(PPEND);*/
var P1 = ColdFusion.getElementValue ("P1");
var P2 = ColdFusion.getElementValue ("P2");
var DT = ColdFusion.getElementValue ("DT");
var PDT = ColdFusion.getElementValue ("PDT");
var url = "workloadForm.cfm?wldID="+wldID+"&P1="+P1+"&P2="+P2+"&DT="+DT+"&PDT="+PDT;
//alert(url);
ColdFusion.navigate(url, "workloadWin");
ColdFusion.Window.show("workloadWin");
}

Comment 33 by Raymond Camden posted on 10/16/2012 at 11:37 AM

You should be able to use JS to check if the value is null.

Comment 34 by Dan posted on 10/25/2012 at 12:46 AM

This has been a particularly big problem for us. As Steve pointed out, browser cache is against us here, at least in my case. I was able to find a browser that exhibited the problems and directly correlate it to our debug reports "WDDX packet parse error at line 1 column 1. Content is not allowed in prolog". We were able to observe an improper argumentCollection as well as the wrong contents for cfajax.js.

The fact of the matter is, browsers are stubbornly ignoring modified resources and have been for several generations. We've had to employ a cache prevention scheme to get clients to grab updated resource content. Similar to http://davidwalsh.name/prev..., but with a CF twist, since we can use the actual timestamp of the resource by calling GetFileInfo(). This helps the client by allowing them to maintain a cache unless we've actually modified something.

Back to the point Steve was making, cfajax.js was changed in 9.0.1 as well as in 10. We recently updated our site from 9.x to 10.x and immediately started receiving the WDDX problem. It took a fair amount of time to understand the cause. After that, it took a fair amount of time to understand what it was doing to our visitors. After that, it took a fair amount of time to figure out a solution that could help some of our visitors. We utilize a lot of <cfajaxproxy ... /> and converting to jQuery wasn't an option. Also, Adobe should be doing a better job with such things as this. After all, who, these days, isn't aware of the heavy caching philosophies of the modern browser?

A solution that has helped, but has not solved the problem was to dynamically load a second copy of cfajax.js with a moc timestamp appended to it. In order for this to work, I also have to destroy the Coldfusion object aka "delete Coldfusion" and then load cfajax,js, but that is not very safe.

@John
The argumentCollection isn't getting encoded, the call back to the CFC is passing a wrong argumentCollection altogether because the callback method inside cfajax.js has changed. Adobe didn't think about the consequences of reusing method names, esp. since they obfuscate their src, problems were undoubtedly going to arise.

Comment 35 by Steve posted on 10/25/2012 at 12:56 AM

Since reporting that my problem was resolved by having IIS pass no cache headers, I find that a few clients still have the problem. Your idea of manually loading a cfajax.js with a timestamp and deleting the Coldfusion object sounds good. Why is it not very 'safe'?

Comment 36 by Dan posted on 10/25/2012 at 8:52 PM

I couldn't get IIS to behave for me, or rather the "stuck" browser never really made the call home to that resource and therefore it never received the new response headers either.

The "not safe" thing I ran into was a race condition where in some cases during the time between deleting the Coldfusion object and re-fetching the cfajax.js, other components in the page were expecting to find the {CF} object and got sadly disappointed. CF gets to include its resources first in line and then immediately begins to init() things by calling ColdFusion.AjaxProxy.init().

I still believe this is hackable to a reasonable solution somehow.

Comment 37 by Matt posted on 10/31/2012 at 12:00 AM

Hi Raymond,
May I ask which version you have ran your code on?
Just intrigued why you didnt see the same problem that I experienced.
Maybe there something different in your setup compared to mine.

Thanks

Matt

Comment 38 by Raymond Camden posted on 10/31/2012 at 12:09 AM

Now I'm running 10. At the time of this blog entry it would have been 9.

Comment 39 by avejidah posted on 12/18/2012 at 1:42 AM

Arrrrg, same stupid caching issue. We use cfajaxproxy and our clients are getting the same WDDX error.

First thing I tried (prior to googleing and finding this page) was to clear my cache, which of course resolved the issue for me. Now we have the issue that tons of our clients are getting this WDDX issue, and we cannot find a solution. I added HTTP headers to prevent caching in IIS, but - although I do see the response headers - that is not working for our clients. My understanding is that what Dan said is correct: "[...] browser never really made the call home to that resource and therefore it never received the new response headers either."

Can anyone think of any method of resolving this quickly? We use jQuery for all of our ajax now, but we still have a very large site with a ton of legacy <cfajaxproxy> calls.

Comment 40 by avejidah posted on 12/19/2012 at 12:48 AM

For any other poor soul experiencing this issue, we did the following to fix it:

1) Added no-cache headers to the /CFIDE/scripts/ directory in IIS (Cache-Control: no-cache, no-store; Pragma: no-cache; Expires: `old date here`).
2) Renamed the component which was being used in the cfajaxproxy call.
3) Made a copy of /CFIDE/scripts/ (we named it /CFIDE/scripts2/). In CF Admin->Settings, changed ScriptSrc directory to /CFIDE/scripts2/.

Seems like the second one is what actually fixed the issue, but those were the steps we took. Our helpdesk is no longer receiving a flood of emails, so we feel that the issue is now resolved.

Comment 41 by Raymond Camden posted on 12/19/2012 at 12:50 AM

Thanks for posting that Avejidah!

Comment 42 by hprice posted on 7/7/2015 at 7:31 PM

I am now having this issue after upgrading to CF11 Update #5 on Win2008 R2 IIS 7.5.

I tried the 3 steps mentioned by @avejidah and also adding meta tags to no avail.

Has anyone had this problem when upgrading to CF11?

Comment 43 (In reply to #42) by deepinthecode posted on 2/24/2016 at 10:43 PM

Yes! I am - were you able to solve this issue? And if so, what did you do? Thanks!