Forcing ColdFusion to recognize changes made to data used for Ajax bindings

This post is more than 2 years old.

While I'm definitely a jQuery fanboy to the extreme, I still have quite a bit of respect for the Ajax stuff that ships out of the box with ColdFusion 8. One of the slickest features is bindings. I love how you can simply say, "This form element monitors another and loads this URL for data." I mean look at this example:

<cfselect bind="cfc:ajax.remoteCowBellService.getCowBellLocations( {cowbellid} )" name="locationID" id="locationId" bindonload="true" queryPosition="below" display="name" value="id"> <option value="0">Choose a location ...</option> </cfselect> In the above example, the drop down has its data populated by the result of a CFC call. The use of {cowbellid} will "link" to a form field that that name or ID. When that changes, ColdFusion handles rerunning the Ajax call to populate the drop down. Brain dead simple.

However (isn't there always a however) there is one small problem with bindings. If you ever change a value via JavaScript, and not via 'real' user interaction, then the code behind the bindings do not notice the change.

I created a simple demo to help demonstrate this and the fix I found. First, my Ajax application:

<script type="text/javascript" src=""></script> <script> $(document).ready(function() {
$('#button').click(function() {

}) </script>

<cfform name="fooform"> <cfinput type="text" name="name" id="foo"> <input type="button" id="button" value="test"> </cfform>

<cfdiv bind="url:test3.cfm?foo={name}" />

Real impressive, right? The cfdiv is boudn to the name form field (notice I can use the name value, not the ID). When I enter stuff in the name, and then click elsewhere, ColdFusion will automatically note the change and fire off the URL request. Each type of form field that supports bindings will have a default event type to use. In this case it is "change". I can change that by using @XX on my bind to specify another event, just remembering to not include "on". So onKeypress would be: {name@keypress}.

Alright - so I added a button and used jQuery to listen in to the click event. jQuery is not required for what I'm demonstrating today, but as I now do everything with jQuery, I just figured it would be quicker.

I spent about an hour digging into cfajax.js. This is one of the core files automatically included when you use bindings. I combined this with Firefox and the awesome dir command. While cfajax.js is pretty obtuse (to help save size), I noticed the core object created was named ColdFusion. I began my investigation then by doing:


Repeat after me. If I have not installed Firebug, I will do so today. Anyway, this gave me enough information to help me dig into the proper function with cfajax.js:

$E.callBindHandlers=function(id,_1e9,ev){ var el=document.getElementById(id); if(!el){ return; } console.log('EXISTED') var ls=$E.listeners; for(var i=0;i<ls.length;i++){ console.log((ls[i].ev==ev)+' ev is '+ev+' want is '+ls[i].ev) if(ls[i].el==el&&ls[i].ev==ev&&ls[i].fn._cf_bindhandler){ console.log('FOUND MATCH') ls[i],null,ls[i].params); } } }

As you can see, I added a few log messages in there to help me debug. Turns out the basic syntax you need is:

callBindHandlers(IDNAME, null, EVENTYPE)

So I tried this:

$('#button').click(function() { ColdFusion.Event.callBindHandlers('foo',null,'change') })

In this case I switched to the ID, not the name, and it was important that I matched my event type as well. This worked wonderfully. As I clicked the button I saw the Ajax requests being fired off. To be real sure, I did this as well:

$('#button').click(function() { $('#foo').val(999) ColdFusion.Event.callBindHandlers('foo',null,'change') })

This worked wonderfully as well. Anyway, I hope this helps others. Obviously this is not documented, so use with care. I'm going to file an official ER with the ColdFusion team to see if this can be exposed and supported.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Edward Beckett posted on 7/8/2009 at 10:42 PM

That's Just What I Needed ...

More Cowbell ...

Comment 2 by todd sharp posted on 7/8/2009 at 10:59 PM

There's also ColdFusion.Bind.assignValue - see:

Comment 3 by James Lamar posted on 7/9/2009 at 7:53 PM

Could you include all the working files? I'm in process of learning jQuery and AJAX mixed with CF and I'm having trouble following. It would help to see a complete working sample with cfc and all. Thanks.

Comment 4 by Raymond Camden posted on 7/10/2009 at 2:15 AM

I don't have the code anymore. Sorry. The main file's CFDIV was something like:

<cfdiv source="url:test3.cfm?name={name}" />

Comment 5 by Darrin posted on 10/19/2011 at 12:07 PM

How about setting N related list

I have twolist:
<cfselect name="actioningDD" id="actioningDD" bind="cfc:rfi.cfcs.RFIs.rfi_getActioningItems()" bindonload="true"/>

the other: <cfselect name="elementDD" id="elementDD" bind="cfc:rfi.cfcs.RFIs.ref_getElements({actioningDD})" />

in a js file I set the first list using :

but when I set the value of the second using :

it does not set the list to that item as being selected.

ANy ideas?

Comment 6 by Raymond Camden posted on 10/19/2011 at 4:24 PM

How could it though? In a typical related list "UI metaphor" (forgive the fancy words there), items in B are driven by a selection in A,not the other way around. You may have items in B that show up with select you A[1] and A[N]. It isn't always a unique set per every selection in A. Therefore, there is no way to assume A[N] based on B[N]. (IMHO)