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
How would you add a "Clear" button?
I'm working on a part 3 for the original questioner, I'll try to get that in as well.
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
When you use Firebug, or Chrome Dev Tools, what does the Ajax response look like?
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.
You don't see _any_ Ajax response? There is definitely one there. Is this online where I can see?
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
So are you running the same code as me then? The request is what's bad - as you said.
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 <cfset foo=CreateObject("component","captcha").createCaptcha()>
but it fails in 9.0.1 when invoked via a JS function, like so:
<cfajaxproxy cfc="captcha" jclassname="cfimageCaptcha">
<script language="Javascript">
var refreshCaptcha = function() {
var jsCaptcha = new cfimageCaptcha();
jsCaptcha.setCallbackHandler(populateCaptcha);
jsCaptcha.createCaptcha();
}
</script>
Spark any ideas?
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.
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.
This would normally be a paid engagement for me, but if you want to ping me via email I can take a quick look.
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.
What do you see with Firebug or Chrome Dev Tools?
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.
Hi,
We are having the same issue of CF 9.0.1 breaking the CF Ajax Tag.
Is there any solution for this issue?
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.
Thanks Ted for your response. Can you please show code sample of how to call JQuery and AJAX?
Thanks.
http://docs.jquery.com/Tuto...
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.
@Steve: The same problem as who? I don't believe the earlier commenters said anything cache related.
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.
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?
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.
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.
@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.
Either that or I am just wrong. I'll take another look. Maybe I screwed something up the first time.
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
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.
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.
Best I can recommend is switching to a pure jQuery solution instead. You can also open a tech support request too.
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");
}
You should be able to use JS to check if the value is null.
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.
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'?
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.
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
Now I'm running 10. At the time of this blog entry it would have been 9.
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.
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.
Thanks for posting that Avejidah!
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?
Yes! I am - were you able to solve this issue? And if so, what did you do? Thanks!