Copy link to clipboard
Copied
i have a cfgrid bound to a text field as well as a cfc
text field passes a value to cfc where it's being used as a parameter for a query . query can return zero records, when that happens, browser throws a json error
how can i trap this error inside the cfc and return a message to user? (without using a proxy)
thanks
well, some people would say it's crazy to work a full day on throwing an alert, and i tend to agree. Thanks everybody for suggestions, for what it's worth, this is how it works:
do NOT specify the onLoad event in cfgrid, do NOT use ajaxonload.
instead, create this js function, with THIS particular syntax:
getTotalApps = function() {
var isGrid = ColdFusion.Grid.getGridObject('myGrid');
var isData = isGrid.getStore();
isData.addListener("load",function() {
if(isData.totalLength == 0)
{
...
Copy link to clipboard
Copied
sounds like if/else 101 to me. What would you like to happen if 0 records are applied.
Copy link to clipboard
Copied
Thanks for answering,
i've tried the obvious <cfif myQuery.recordCount eq 0> No records found<cfabort><cfif>
however, looks like inside a cfc <cfabort> simply doesn't work, the cfc is trying to return the structure to the calling cfm anyway and the structure is empty, hence the json error
i've also tried (with same result)
<cfif myQuery.recordCount eq 0>
<script language="JavaScript">
alert("No records found");
</script>
</cfif>
Copy link to clipboard
Copied
i found the reason, the text field the grid is bound to is taking its values from an Oracle database, which is case sensitive. my query was matching the search param on lower(myColumn) on the WHERE clause, but didn't bother to do the same on the SELECT lower(myColumn). as a result, the value of the text field could have both upper and lower case chars, while the query could have only lower.
soon as i changed the qry to select lower(myColumn) where lower(myValue) the error went away
thanks
Copy link to clipboard
Copied
but i still didn't figure how to throw a "No records found" message for user
Copy link to clipboard
Copied
ion wrote:
but i still didn't figure how to throw a "No records found" message for user
<cffunction name="f" returntype="Any">
<cftry>
<cfquery name="myQuery">
</cfquery>>
<cfif myQuery.recordCount eq 0>
<cfthrow message="Query returns no records">
</cfif>
<cfcatch type="any">
<cfreturn cfcatch.message>
</cfcatch>
</cftry>>
</cffunction>
Copy link to clipboard
Copied
Why are you going through the motions of raising an exception, only to catch it and then return the very message you threw in the first place? Why don't you just return the message directly? What are you getting out of the try/throw/catch approach you're using here?
It might be fair enough to raise an exception in situations in which there are no records, but you shouldn't catch it in th same context you throw it (it defeats the purpose of using an exception in the first place), just let the exception bubble up to the calling code, and let that code decide what to do with it.
--
Adam
Copy link to clipboard
Copied
Adam Cameron. wrote:
Why are you going through the motions of raising an exception, only to catch it and then return the very message you threw in the first place? Why don't you just return the message directly? What are you getting out of the try/throw/catch approach you're using here?
It might be fair enough to raise an exception in situations in which there are no records, but you shouldn't catch it in th same context you throw it (it defeats the purpose of using an exception in the first place), just let the exception bubble up to the calling code, and let that code decide what to do with it.
I agree, and hope Ion will note this. I have assumed he might want to run more business code in the catch and/or to manage the return. To have the exception percolate up the call stack, one could do something like
<cffunction name="f" returntype="Any">
<cfquery name="myQuery">
</cfquery>
<cfif myQuery.recordCount eq 0>
<cfthrow message="Query returns no records">
</cfif>
</cffunction>
Copy link to clipboard
Copied
thanks Adam, BKBK, but looks like cfthrow inside a cfc behaves like the other tags i've tried, i can't really control it
to my actual message, "No records found" it adds its own stuff that i don't want the users to see, like:
Error invoking CFC /.../mycfc.cfc: No records found [Enable debugging by adding 'cfdebug' to your URL parameters to see more information]
i've tried initializing all cfthrow attributes to blank, like: type = "any" detail = "" errorCode = "" extendedInfo = ""
with same result.
Copy link to clipboard
Copied
ion wrote:
looks like cfthrow inside a cfc behaves like the other tags i've tried, i can't really control it
Not necessarily. See my previous example.
However, note what Adam said. Throwing an exception is a powerful tool that should not be wasted on an example like this one. It would be preferable to just return the string "No records found".
But, you may ask, what if the function is engaged in some other business which requires it to, for example, return an array. Then you could make the function's returntype a struct. The struct would then contain an array and a string! It goes like this
<cffunction name="f" returntype="struct">
<cfset var myReturnStruct = structNew()>
<cfset myReturnStruct.values = arrayNew(1)>
<cfset myReturnStruct.status = "">
<cfquery name="myQuery">
</cfquery>
<cfif myQuery.recordCount eq 0>
<cfset myReturnStruct.status = "Query returns no records">
</cfif>
<!--- Etc., etc., including business code that writes to the array myReturnStruct.values --->
<cfreturn myReturnStruct>
</cffunction>
Copy link to clipboard
Copied
thanks again BKBK, but there isn't any calling code, it's just a cfgrid bound to the cfc. i know i could turn it into a proxy and use the proxy to manipulate the grid (and the alert message), but this is simply too much work just to send a text message to the user, which is all i want
your suggestion, to insert the message into the returning struct from cfc won't work very well either, the message will appear inside the grid, and i don't want that
regards
Copy link to clipboard
Copied
kind of half of a solution i found, is to attached a js function to the onLoad event of the grid, on the caller page, like:
getTotalApps = function(){
var isGrid = ColdFusion.Grid.getGridObject('myGrid');
var isData = isGrid.getStore().totalLength;
if (isData == 0) {alert("No records found"}
}
however, this only works the first time page is loaded, not every time the grid changes, and since the onChange event is already occupied by the cfc, i can't put it there
i was NEVER able to make <cfset ajaxonload("getTotalApps")> to work in ie8. if i put javascript within <head></head> tags, it renders a blank page with error "DOM is null or not an object"
if i remove the <head>, function doesn't get executed
Copy link to clipboard
Copied
ion wrote:
kind of half of a solution i found, is to attached a js function to the onLoad event of the grid, on the caller page, like:
getTotalApps = function(){
var isGrid = ColdFusion.Grid.getGridObject('myGrid');
var isData = isGrid.getStore().totalLength;
if (isData == 0) {alert("No records found"}
}
however, this only works the first time page is loaded, not every time the grid changes, and since the onChange event is already occupied by the cfc, i can't put it there
i was NEVER able to make <cfset ajaxonload("getTotalApps")> to work in ie8. if i put javascript within <head></head> tags, it renders a blank page with error "DOM is null or not an object"
if i remove the <head>, function doesn't get executed
Everything points to one of the simplest solutions possible, namely:
<cffunction name="f" returntype="string">
<cfset var message = "">
<cfquery name="myQuery">
</cfquery>
<cfif myQuery.recordCount eq 0>
<cfset message = "No records found">
<cfelse>
<cfset message = myQuery.recordCount & " record(s) found">
</cfif>
<cfreturn message>
</cffunction>
Copy link to clipboard
Copied
BKBK, the cfc is bound to a grid so it must return a structure. you can't change returntype on the fly
Copy link to clipboard
Copied
ion wrote:
BKBK, the cfc is bound to a grid so it must return a structure. you can't change returntype on the fly
Please ignore. I posted that without realizing you already had an answer.
Copy link to clipboard
Copied
there isn't any calling code, it's just a cfgrid bound to the cfc.
Ah, sorry: I came into this late and didn't read the earlier posts.
<cfgrid> has an onerror handler for when - I presume - a bind operation fails. Does this not give you what you want? The JS function can do anything, after all.
Reading here:
That said, I dunno how to send the message back from the server, but in this case perhaps you don't: you're just trying to pass back a hard-coded string if you get an error, so why not simply hard-code the message in the <cfgrid> code?
I've never used this functionality before, so I'm pretty vague on how it works... if it sounds like it'll work, then perhaps google about a bit. Or maybe someone else here is au fait with how it all comes together..?
--
Adam
Copy link to clipboard
Copied
well, some people would say it's crazy to work a full day on throwing an alert, and i tend to agree. Thanks everybody for suggestions, for what it's worth, this is how it works:
do NOT specify the onLoad event in cfgrid, do NOT use ajaxonload.
instead, create this js function, with THIS particular syntax:
getTotalApps = function() {
var isGrid = ColdFusion.Grid.getGridObject('myGrid');
var isData = isGrid.getStore();
isData.addListener("load",function() {
if(isData.totalLength == 0)
{
alert("No records found");
return false;
}
});
}
ColdFusion.Event.registerOnLoad(getTotalApps,null,false,true);