A user posted a question to my forums that I thought would make for interesting blog matter. It concerns ColdFusion, binding, and results with leading zeros. I touched on this before (Interesting ColdFusion 8, AutoSuggest issue to watch for) so this may be something folks are aware of already. Here is some background. Imagine a CFC with this simple method:
<cffunction name="getKey" access="remote" returnType="string">
<cfreturn "001234">
</cffunction>
Notice the result is a number, but with zeros in front. If you bind this to something on the front end:
<cfdiv bind="cfc:test.getkey()" />
You will only see 1234, not 001234. If you inspect the HTTP call with Firebug, you can see that the server returned 1234.0. ColdFusion took care of dropping the .0 at least, but this is not a desirable result. As mentioned in the earlier blog post, this seems to be the nature of the JSON serialization in ColdFusion. I can think of two simple ways around this.
One way would be to bind to a JavaScript function that then used cfajaxproxy to call the back end. Your back end cfc would need to prefix the result so the zeros aren't dropped. Like so:
<cffunction name="getKey2" access="remote" returnType="string">
<cfreturn "pre" & getKey()>
</cffunction>
My problem with this solution is that your mucking with your model code. You shouldn't need to do that. Luckily there is another way to handle this. Don't forget that CFCs (in ColdFusion 8 at least) support a plain return format. Plain meaning "don't do squat to my result, just return it!". So if I change my cfdiv to:
<cfdiv bind="url:test.cfc?method=getkey&returnformat=plain" />
It works as expected now. I'm still using my CFC, but I've switch to the URL format. It's a bit more verbose, but at least my model CFC isn't changed.
Archived Comments
To complicate this more, try using a 32 character string made up of numbers. (I only say 32 because that's where it's stung me recently. Other strings are probably impacted too)
IE: 12345678901234567890123456789012
This gets converted to scientific notation! I've never been able to get the format=plain recommendation to solve this issue but I've seen others who have. I decided to just prepend a space to the string and hope no one notices.
This was the bug/fix I wasn't ever able to get working for you. Has anyone else been able to repro the issue you had? (I mean my fix to the issue not working for you - not the original issue.)
Thanks for looking into this. I guess I need to convert my current bind statment for cfgrid bind="cfc:dir.services.subenditem.getPartPubData({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})" to use URL bind instead. So i used bind="url:/dir/services/subenditem.cfc?method=getPartPubData&returnformat=plain&page={cfgridpage}&pagesize={cfgridpagesize}&sortcolumn={cfgridsortcolumn}&sortdirection={cfgridsortdirection})" which seemed to work OK, but error occurs: Only simple and XML variables may be returned when the returnFormat is plain.
From Help file:
# plain: ensure that the return value is a type that ColdFusion can convert directly to a string, and return the string value without serialization. Valid types include all simple types, such as numbers, and XML objects. If the return value is a complex type, such as an array, or a binary value, ColdFusion generates an error. If you specify a returntype attribute, its value must be any, boolean, date, guid, numeric, string, uuid, variablename, or XML; otherwise, ColdFusion generates an error.
So I am still stuck.
I guess the simplest solution is the best solution for me. I amde my select statement to be SELECT ' '+[PARTPUB_NUM] AS PARTPUB_NUM, ... which prepend a space. As a result leading zeroes are preserved, too.
On grid update I jusst trim the value, which trims the leading space. So in the circle it goes and it seems to work. I just wish we did not have to do things like that.
Ah, in my example it was just a cfdiv, not a complex UI item. Sorry I missed that! But I'm glad you got it working at least.
I've been spending a lot of time trying to fix this issues and I also have googled the problem hoping to find solution to this situation with no success.
When I found this site and read Giedrius I tired to do the same by adding a spece on the select statement but unfortunately the leadng zeroes are still cut by cfgrid.
I'm so frustrated with Coldfusion, why would someone be so dumb creting cfgrid and to cut out leading zeroes especially when the datatype is set as varchar at the db level?????
I tired everything, none is working including bind:url
Coldfusion is just plain stupid!
Well Alec, I definitely appreciate your frustration, but I'll disagree that CF is stupid. All platforms have issues, and this is just one of CF's.
Alec, if you modfify Giedrius solution to add a + in front, does it work? (Don't worry if you see a + in the grid, we can fix that next.)
Actually, a + may be bad. Try +, but if it doesn't work, try something like @ or #.
Hey Ray, here's a weird one for you, if you bind a cfinput and a cfdiv side by side to a function that returns a string with a leading zero (in my case the zip code 02664) the cfinput will have a completely different result (and four digits to boot)! The cfdiv works as expected though. The right value is coming back from the cfc, but CF decides to change the result completely if it is going into a cfinput.
Strange!
@Seth: I'd log a bug report on that. (www.adobe.com/go/wish)
Consider it done :)
Not sure how you guys are doing it. But I basically found just saving the entries with leading zeros with a leading space.
Seams the Json return format is chopping off the leading zero unless there is a space in front of it.
Hope this helps someone
Just discovered that by adding the securejson="true" attribute to the CFFUNCTION tag, the leading zeros are preserved on the return, at least in CF9.0,1.
As a side note I've been resolving this issue by padding something like "GETRIDOFME" on the json return and just using the replace function on the javascript side on the return.
document.getElementById('fieldname').value = results[0][3].replace('GETRIDOFME','');
Just to be anal, I'd go with a smaller string - just to make the network traffic a bit nicer.
What if the cfc is in a different folder called cfcomponents? I tried:
<cfselect name="ADVCITIZENSHIP" bind="url:cfcomponents/AjaxStuffs.cfc?method=getADVCit&returnformat=plain" bindonload="true"/>
I got a vertical error window that says: Error parsing JSON response. Please help!
Why did you specify returnFormat=plain in the URL?
I used the following and I lost the leading zeros:
<cfselect name="ADVCITIZENSHIP" bind="cfc:cfcomponents.AjaxStuffs.getADVCit()" bindonload="true"/>
So I thought I would try using url instead & hoping I could have a different result
Awesome