Shirzad (cool name!) asks:
There are a couple ways of handling errors with ColdFusion 8's Ajax features. Here is a quick overview of some of them in regards to the cfdiv tag. First, let's make an error. I'll take a simple cfdiv:How do you prevent the Coldfusion Ajax alert message "error retrieving markup..."? Sometimes errors are inevitable. I want to prevent users on our public site from seeing the javascript alert that pops up whenever there's an error in a coldfusion ajax container (or at the very least change the message so it isn't asking people to add cfdebug to the parameters). Is there any way to do this?
<cfdiv id="testdiv" bind="url:test2.cfm"/>
And here is test2.cfm:
<cfthrow>
As you can guess, this will immediately throw an error when loaded by the div. The cfdiv tag supports an onBindError attribute. It lets you specify a JavaScript function to run when an error occurs (big surprise there). Here is a modified version of our original script:
<script>
function handleError(c,m) {
console.log('error '+c+' '+m);
}
</script>
<cfdiv id="testdiv" bind="url:test2.cfm" onBindError="handleError"/>
The docs specify that the error handler should take two arguments - a status code and message. When I ran this, I correctly saw the error log, but I also saw the 'naked' CF error in the div. I thought perhaps that the onBindHandler would automatically hide the error but it doesn't. I then tried this:
document.getElementById("testdiv").innerHTML = "Error!";
But for some reason, it wouldn't work. I was able to get this to work:
ColdFusion.navigate('/user.cfm','testdiv');
The file user.cfm was just another random file on my server. You would normally point it to a file that had some kind of 'Error' message.
Another option is to specify a global error handler. This is done with the setGlobalErrorHandler:
function handleGError(s) {
console.log('global error called '+s);
}
ColdFusion.setGlobalErrorHandler(handleGError);
Notice though that this function only takes one argument, a message. I don't know why - but it seems to me as if it should work the same as the error error. Anyway, if you use this, and remove the onBindError, the global error handler will fire.
As yet another example of how you can handle errors, the cfajaxproxy tag has an onError attribute. You can also set a specific error handler for an instance of an AjaxProxy object.
Check the docs for other tags and how they can provide support for this as well. (Consider this my "This your homework" part.) CFGRID for example supports onError which works the same as the onBindError for cfdiv.
Archived Comments
I am using CFAjaxProxy with cfc's and when I call a cfc that has an sql syntax error a page returns to the HTTP request that displays the error. Well the returned page does not get handled like an error because it's status code is 200 and the Response Header does not equal server-error. And since it is not a proper response it does not get sent to the callback handler. What I need to do is handle all possible errors, so that the user is not sitting and waiting for a response when none will ever come. Any ideas?
This is how the cfajax.js determines if a response is an error.
$A.isRequestError=function(req){
return ((req.status!=0&&req.status!=200)||req.getResponseHeader("server-error"));
};
Ah, so you have CF handling errors as well, which means you get a 'pretty' error.
So here is an idea - use onError to handle the errors, and if the error occurs on an ajax request (you can sniff the request), you could just throw a new exception.
Yes, u can use CFHEADER and send a non 200 HTTP Status Code.
I have a function that is being called through cfajaxproxy that throws a java.lang.NullPointerException with no other detail. But the interesting thing is it only throws the error when called from cfajaxproxy. Invoke it normally through cfinvoke and it works perfectly. I can see that all the parameters are passed fine as they are logged. If I comment out the error handler in the cfc it throws a generic Status: 500 internal server error. Neither error is much help in figuring out what is wrong. Any suggestions as to how I can determine whats causing it would be appreciated.
Don't test it via cfinvoke. Test it via your browser. Ie, use Firebug to see the URL and paste it into a new tab.
Ray: thanks as always for you prompt response!
That took me right to the line of code that was causing the problem. Excellent! Thank you!
Ray: Thanks so much for your help on this - much appreciated. One container I'm still having an issue with is the cflayout-tab. Any ideas how to handle errors that give you the javascript alert from in there (other than a cfcatch)?
Did you try the global error handler I described above? I haven't tried it for a cflayout error, but I'd give it a shot.
Ray: I managed to get the global error handler working for an error in a cfdiv (and even for a cfdiv that's inside a cflayout-tab), but no luck so far with an error in a cflayout-tab. But maybe I'm not doing something right. If anyone can get it to work with a tab, please let me know.
I got it working. I used the global handler, although cflayoutarea supports onBindError as well. I then gave the tab a name, and was able to use ColdFusion.navigate to send the tab to an error page.
OK - thanks Ray. I'll figure out why my code's not working properly. Again, really appreciate your help on this.
How could I launch a javascript function to display a "pretty" error message if the ajax binding on cfgrid returns a messy JSON error? It seems cfgrid doesn't have an onBindError attribute.
Thanx,
Tony
Use onError:
<cfgrid autowidth="true" name="entries" format="html" width="600" bind="url:getentries2.cfm?page={cfgridpage}&pagesize={cfgridpagesize}&sort={cfgridsortcolumn}&dir={cfgridsortdirection}" onError="handleError">
Ray,
That didn't work when there was an AJAX error. It just threw the typical CF javascript popup with alert recommending to turn CFDEBUG on. It didn't call the handleError function. Any ideas what may be happening?
Tony
What kind of ajax error? I'd say _any_ error in loading the data is an ajax error.
Ray, Sorry for resurrecting years old post, but I was looking for a solution similar to what's posted here. I have a cfm module that uses cfgrid to call a cfc module to get the data. If for some reason the data is not available, currently cf throws the cfc error (..recommending to turn cfdebug on). Is there a nicer way to handle error messages? I did see a similar post above where you said to use "onerror="handleError"" but that doesn't seem to work well. When I add the onerror the page falls apart. Here is the piece of code where i added onerror -
<cfset args.bind = "cfc:pagination.casetransbind.getCaseTrans({cfgridpage},{cfgridpagesize}, {cfgridsortcolumn},{cfgridsortdirection}, #case_tmp#)"
onError="ErrorRoutine">
Any idea what I'm doing wrong?
When you say the data is not available, do you mean the DB is down, or you are returning 0 items back? Because 0 items back should work just fine.
Well, to elaborate the data, I'm parsing an XML file that is returned from Cobol module and building a query in cfc and then returning the data back to cfm using QueryConvertForGrid. For example, I entered case number, and if the case has any detail info, it returns the detail info nodes in the XML. Otherwise DB2 returns only the basic info. When detail info node is not available, CFC throws the error. In CFC, I'm looking for that detail info node. I'm also checking for the node existence in cfc and if not available, throw error message. But I'm not sure if I'm doing it right for cfgrid to capture that error. so here is the error capture in cfc -
<cfif Not IsDefined("DetailNode")> <cfset err_msg = Insert("#AppErrorMsg#<br />", err_msg, Len(err_msg))> <cfreturn err_msg></cfif>.
Well wait - do you want the grid to show a friendly error, or just no data? If you just want to to show no data, handle the error in your CFC and return an empty record set.
I would like to grid to show a friendly error instead of an empty grid. Like 'No detail records found". I think I'm handling the error in CFC but it doesn't seems to be appearing on the grid. If I take off the onerror function, I get "DetailNode is undefined in the XML with cfdebug info" popup message. Instead of that popup message, would like to display it on the grid.
Can't help you there - sorry. I don't use cfgrid, nor do I recommend anyone else use it. That doesn't help you, but I'd rather tell you that then nothing at all. ;)
Thanks. When you are saying you don't recommend cfgrid, what other ways do you recommend. I'm flexible if you have other recommendations.
Read these entries: http://www.raymondcamden.co...
Ray, just wanted to circle back to this issue and let you or anyone who is interested know i did the following steps as a work around -
My first mistake was on the CFC page i was returning the error messages by using cfreturn. I should know better. Anyway, changed that to cfthrow.
Second on the CFM page, I wrote a javascript module that is expecting two parms (status, text). And display the text using innerhtml to display it on the screen instead of cf default popup message with cfdebug in it.
Third - I'm calling the javascript from cfgrid onerror event.
That worked for me.