ColdFusion Ajax Bindings - Form Fields only?

This post is more than 2 years old.

Jose asks:

I just got started using cfdiv an the other AJAX related tags and I have a question about passing params in the bind attribute. I have the following test code:

<cfinput name="EmployeeID" type="hidden" value="#variables.EmployeeID#" />

<cfgrid name="goals" format="html" striperows="yes" bind="cfc:ab.model.goals.goalsGateway.getGoalsGridRecordSet(page={cfgridpage}, pagesize={cfgridpagesize}, gridSortColumn={cfgridsortcolumn}, gridSortDirection={cfgridsortdirection}, EmployeeID={EmployeeID})">

Does it mean I can only pass filter params for the cfcs I am using thru having those hidden "pass thru" fields? What I am missing?

The short answer is yes. Bindings allow you to speak to JavaScript, CFCs, and vanilla URLs, and they allow you to automatically monitor values of form fields. (As well as events.) But it doesn't mean you have to use a hidden form field as you have here. You could have simply hard coded the value like so:

bind="cfc:ab.model.goals.goalsGateway.getGoalsGridRecordSet(page={cfgridpage}, pagesize={cfgridpagesize}, gridSortColumn={cfgridsortcolumn}, gridSortDirection={cfgridsortdirection}, EmployeeID=#variables.employeid#)"

Note when I say 'hard coded', what I mean is that the value is still dynamic (see the #s?) but it isn't a client side bound variable.

Just to be clear - this doesn't mean that ColdFusion's Ajax support can only work with form fields. It's just that the bindings to allow for automatic updates are tied to form fields. (And Spry datasets as well, but that's another story.) You can still easily call server side code using cfajaxproxy for example, and pass anything you want, but this does mean you have to write a few lines of JavaScript.

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 https://www.raymondcamden.com

Archived Comments

Comment 1 by todd sharp posted on 8/19/2008 at 5:49 PM

Make sure to be careful when working with this method. Might be best to jsStringFormat the variable to make sure you don't 'break' the JavaScript if it contains funky chars.

Comment 2 by Justin posted on 8/19/2008 at 5:59 PM

I wish there was some sort of guide or "how-to" for getting started with cf8 Layout/Ajax while remaining 508 compliant. The little things you can do and the tags you should avoid. The workarounds you can do.

Nic Tunney was supposed to do a 508 compliant preso at CFUnited, but I wasn't clear what happened there.

Comment 3 by Gary Gilbert posted on 8/19/2008 at 6:30 PM

508 compliance is a touchy issue with any Ajax stuff. I haven't had a chance to play with the most modern screen readers but are they even able to read dynamically generated content via ajax calls?

If you follow the web accessibility guidelines the website should function with javascript turned off so that puts a big no no on Ajax. With 508 compliance accessibility means accessible with assistive technology (screen reader). But that brings us back to the problem of getting hold of a copy of JAWS and seeing if it can handle the EXT UI stuff in CF8

Comment 4 by Justin posted on 8/19/2008 at 6:47 PM

That's why I was especially interested in Nic's preso. He said you can mock up with cflayout stuff and then switch to Ext/YUI to make them compliant.

I thought that some readers supported Ajax calls, as long as the layout degraded gracefully. Ext 3.0 is supposedly going to improve 508 quite a bit, so we'll see.

I've used the CF8 layouts and what not pretty extensively and find them to be :mostly: a time saver. Due to the way CF processes the tags and tries to autoinject all the js, that can the source of a headache or two.

One thing is for sure CF8 has got me back on the javascript bandwagon by initiating my baby steps. Other than jQuery for validation, I had my nose turned up to JS pre-CF8.

Comment 5 by Andy Sandefer posted on 8/19/2008 at 8:28 PM

@Jose
A while back Ray blogged about something else that's pretty handy where you can use a cfdiv bound to a URL and then use a simple IsDefined test on the page that's looking for the URL variable. If it doesn't exist then set it (as in to keep your grid that's looking for the URL var so that it doesn't explode). Here's a some code that I wrote for a client recently (a file manager) that shows a listing of files in a cfgrid that is bound to a cftree. The automatic handling of listeners in CF8 is a very powerful feature and if you look very closely at my grid you'll see how I'm pulling of some fast find aka filter as you type voodoo in the searchFilter control above my cfgrid. This let's the user quickly filter down a big list of files that exist within the folder that they're clicking on in the cftree. At any rate, bindings are awesome and I'm pretty convinced that if you can dream it you can build it with CF8!

<cfajaximport tags="cfwindow, cfform">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><cfoutput>#APPLICATION.titleText#</cfoutput></title>
<link rel="stylesheet" type="text/css" href="../css/main.css" />

<script>
function getSelectedTreeVal() {
var selectedTreeVal = ColdFusion.getElementValue('userFileTree','fileManager','node');
return(selectedTreeVal);
}

function invokeUploader() {
var selectedVal = ColdFusion.getElementValue('userSelected','fileManager');
if (selectedVal == '') {
alert("You Must Select the Customer Folder that you wish to Upload Files to...");
}
else {
day = new Date();
windowID = day.getTime();
window.open('uploader.cfm', windowID, 'directories=no, location=no, menubar=no, resizable=no, scrollbars=yes, status=no, titlebar=no, toolbar=no, height=550, width=700');
}
}

function refreshFileTree() {
ColdFusion.Tree.refresh('userFileTree');
}

function showRenameFile() {
day = new Date();
renameFileWindowID = 'renameFile' + day.getTime();
selectedFilename = ColdFusion.getElementValue('gridFilestoreDisplay', 'fileManager', 'CompleteFilename');
var targetURL = 'renamefile.cfm?formName=' + renameFileWindowID + '&currentFilename=' + selectedFilename;

var windowOptions = new Object();
windowOptions.width = 480;
windowOptions.height = 360;
windowOptions.center = true;
windowOptions.modal = true;
windowOptions.resizeable = true;
windowOptions.initshow = true;
windowOptions.draggable = true;
windowOptions.closeable = true;
windowOptions.headerstyle = 'font-family: verdana; background-color: #0066FF;';

ColdFusion.Window.create(renameFileWindowID, 'Rename File', targetURL, windowOptions);

//alert(targetURL);
//window.location = targetURL;
}

function closeFileRenameWindow() {
ColdFusion.Window.hide(renameFileWindowID);
ColdFusion.Grid.refresh('gridFilestoreDisplay', true);
}

</script>

</head>

<cfinclude template="appmenu.cfm">

<body>
<cfoutput>
<cfform name="fileManager" format="html" style="font-family:Verdana; font-size:11px;">
<div align="center" style="border:medium; border-color:black;">
<cflayout type="HBox" style="width:980px; background-color:##FFFFFF;">
<cflayoutarea style="width:320px; height:526px; background-color:##FFFFFF;" overflow="AUTO" align="LEFT">
<cftree name="userFileTree" format="html" font="Verdana" fontsize="11px">
<cftreeitem bind="cfc:#APPLICATION.fileMgmtLib#.getFileTree({cftreeitempath}, {cftreeitemvalue})">
</cftree>
<cfinput type="hidden" name="userSelected" bind="{fileManager:userFileTree.node}">
</cflayoutarea>
<cflayoutarea>
<table style="background-color:##FFFFFF;">
<tr>
<td class="fieldLabel">Search Filter
<cfinput type="Text" maxlength="255" size="40" name="searchFilter" onkeyup="ColdFusion.Grid.refresh('gridFilestoreDisplay', true)">
</td>
</tr>
<tr>
<td>
<cfgrid name="gridFilestoreDisplay" format="HTML" font="Verdana" fontsize="11px" striperows="Yes"
width="650" height="470" pagesize="40" colheaderfont="Verdana" colheaderfontsize="11px" bindonload="No"
bind="cfc:#APPLICATION.fileMgmtLib#.getFilestoreForGrid(
searchDir={userFileTree.node},
typeFilter='File',
searchFilter={searchFilter},
page={cfgridpage},
pageSize={cfgridpagesize},
gridSortColumn={cfgridsortcolumn},
gridSortDir={cfgridsortdirection})">
<cfgridcolumn name="CompleteFilename" display="No">
<cfgridcolumn name="Name" header="Filename" width="350">
<cfgridcolumn name="SizeDisplay" header="Size KB" width="80">
<cfgridcolumn name="TypeImageName" header="Type" width="50">
<cfgridcolumn name="DateTimeDisplay" header="Date Modified" width="150">
</cfgrid>
</td>
</tr>
<tr>
<td align="right">
<cfinput type="Button" name="btnDelete" value="Delete">
<cfinput type="Button" name="btnRename" value="Rename" onClick="showRenameFile();">
<cfinput type="Button" name="btnUpload" value="Upload" onClick="invokeUploader();">
<cfinput type="Button" name="btnDownload" value="Download">
</td>
</tr>
</table>
</cflayoutarea>
</cflayout>
</div>
</cfform>
</cfoutput>
</body>
</html>