Ask a Jedi: Trouble with ColdFusion.Ajax.SubmitForm

Andy asks:

This is probably a stupid question but I can't seem to get this to work. I'm using a ColdFusion.Ajax.submitForm and I thought that I would be able to return something from the form's submit handler page using my callback function. I can't seem to get this to work. I tried to a variable on the submit handler page to give it back to the caller page where the form lives but I just get a giant javascript dialog when I try to test this out using an alert in the callback function to display my callbackMsg. Should I be taking a different approach? I really need to get the primary key of the newly inserted record back and can't seem to return it to the calling page.

Now now, Andy, as we all know, there are no stupid questions, just stupid programming languages. That being said, I have a good idea of what you are running into.

Let's start with a super simple example. I'll build a form with two text fields. These fields will represents two numbers. A third field will be used for the answer. Finally I'll add a button:

<form id="myform">
<input type="text" name="number1"> +
<input type="text" name="number2"> =
<input type="text" id="result">
<input type="button" value="Solve" onclick="solve()">
</form>

Notice that the onclick runs solve. Let's look at that:

function solve() {
   console.log('running...');
   ColdFusion.Ajax.submitForm('myform','test.cfm',resultHandler);
   console.log('done...');
}

First and foremost - look at my use of console.log. You need to stop using Alert. I know it's easy. But Alert can be a real pain in the you know what. Download Firebug and get used to doing your debugging there. Ok, so in between two debug statements I'm running a submitForm action. I've said to submit myform to test.cfm and then run resultHandler.

I made test.cfm simply cfoutput a random number for testing purposes.

The first thing I ran into was that ColdFusion.Ajax.submitForm didn't exist. Remember that ColdFusion only loads the Ajax functionality it thinks it needed. Since I didn't really use any ColdFusion tags, it didn't load squat. The trick to handle this was discovered by Todd Sharp, just add this to the top of your page:

<cfajaximport />

Ok, so now I can run my application and see the request, how do we handle it, and why is he getting a large alert? First look at a more full test.cfm:

<cfparam name="form.number1" default="0">
<cfparam name="form.number2" default="0">

<cfset form.number1 = val(form.number1)>
<cfset form.number2 = val(form.number2)>

<cfoutput>#form.number1+form.number2#</cfoutput>

(And by the way, I should be more anal with my URL checks in this code.) Now let's look at resultHandler:

function resultHandler(result) {
   console.log('result handler ran...');
   console.log(result);
}

When I ran my test, I noticed that result was indeed a large string with a lot of white space. That could be what you are seeing in the large alert. The white space is simply a result of ColdFusion liking whitespace like a Lohan needs publicity.

We can fix this a few ways. We can reduce the whitespace in the CFM with a simple CFSETTING. But that's kinda boring. When I saw this on ColdFusionBloggers

Cranky Bit: Trimming a String in JavaScript

I added his code (note his regex is missing a \ in front of each s) and ended up with this:

<script>
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,""); }

function resultHandler(result) {
   console.log('result handler ran...');
   console.log(result.trim());
}

function solve() {
   console.log('running...');
   ColdFusion.Ajax.submitForm('myform','test.cfm',resultHandler);
   console.log('done...');
}
</script>

Now when I ran the code I got a nicely trimmed response. I added one more line to set the result value:

document.getElementById("result").value = result.trim();

Comments

Rick Smith's Gravatar I can't say how hard I laughed at the link to "programming languages"
# Posted By Rick Smith | 7/3/08 11:55 AM
Chris Schofield's Gravatar Great information, Ray! Thanks for asking Andy! And not to take away from the post itself, but ditto on Rick's comment. Classic!
# Posted By Chris Schofield | 7/3/08 12:39 PM
Andy Sandefer's Gravatar LOLOLOLOL
The PHP link made me chuckle but the Lohan reference was the real comedy here folks!

Thanks a bunch!
Andy
# Posted By Andy Sandefer | 7/3/08 12:58 PM
Joshua Curtiss's Gravatar Thanks for the link to my post, Ray! The code view plugin for WordPress apparently gobbled up the backslashes in the trim function code and I overlooked that after posting it. It's fixed now. That's what I get for using a PHP-based blogging engine. ;-D
# Posted By Joshua Curtiss | 7/15/08 5:04 PM
Edward Beckett's Gravatar This is the exact problem I'm also having ... I have two CFSelects bound to functions in a CFC to populate the option values asynch. NP there ... However, I'm trying to submit the form to a CFWindow through ColdFusion.Ajax.submitForm and the results don't populate to the destination window.

Here's some code .... The originating form page ...

showIt = function() {
   ColdFusion.Window.create("gotopage","Find a Location","gotopage.cfm",{center:true,modal:true,draggable:true,width:550,height:375})
}

   submitForm = function() {
   console.log('running...'); ColdFusion.Ajax.submitForm("stateLookUp","gotopage.cfm",showIt);
   console.log('done...');
    return false;
   }

<cfform name="stateLookUp" id="stateLookUp" onSubmit="return submitForm()" method="post">
<div id="stateContainer" >
<div align="center"><h3 style="margin-right:150px;">Please Select a State</h3></div>
<cfselect name="state" id="state" bind="cfc:blog.com.bindFcns.getstates()" bindonload="true" value="#form.state#" >
<option name="0">State</option>
</cfselect>
<cfselect name="city" id="city" bind="cfc:blog.com.bindFcns.getcities({state})" value="#form.city#">
<option name="0">City</option>
</cfselect>
<cfinput type="submit" name="submit" value="Submit" id="Submit" />
</div>
</cfform>

-----------------
The Window Page ...
-----------------
<cfparam name="form.state" default="">
<cfparam name="form.name" default="">
<cfparam name="form.city" default="">

<cfoutput>
<p>
The State Submitted &##187; <cfoutput>#form.state#</cfoutput> <br> <br>
The City Submitted &##187; <cfoutput>#form.city#</cfoutput>
</p>
</cfoutput>

Result ... Nada ... Got a clue? :)
# Posted By Edward Beckett | 10/19/08 6:38 PM
Andy Sandefer's Gravatar @Edward
You really don't need to have the submit button and call submitForm() like that. Take the post and the onSubmit out of there and just call submitForm in the onClick of a button. It probably doesn't matter but you also don't need id and name values for the inputs - just use name and let CF do the rest (I doubt if this is causing any problems but it never hurts to simplify your code).
I really don't understand what's going on here but I haven't really seen the entire thing in action so I'll just add that Ajax.submitForm is typically called to pass form data to a handler/script page that interacts with the database. Do you really need to post this stuff? If not then get the values of the selects and send them as URL params through your cfwindow function.
# Posted By Andy Sandefer | 10/20/08 11:30 AM
Edward Beckett's Gravatar @Andy ...
"Ajax.submitForm is typically called to pass form data to a handler/script page"

I'm attempting to send the form data to open in a CFWindow ...

My code's probably not the cleanest I'm sure ... sometimes I'm unsure what is and isn't necessary for a specific scenario and I end up just throwing in everything to "get it working" :)

I think my main problem is in the CallBack ... (showIt) But, I'm not sure ... thanks for your input.
# Posted By Edward Beckett | 10/20/08 11:45 AM
Andy Sandefer's Gravatar If this is some kind of step by step form entry then you can just save it in session vars and then load the page or you can use js to get the values and pass them as URL vars in the showIt function you invoke the cfwindow. You're trying to post to a page and then pull up the same instance of the page that you're posting to in a window object and I don't think that you can do that.
# Posted By Andy Sandefer | 10/20/08 11:54 AM
Chris's Gravatar Can you use ColdFusion.Ajax.submitForm with a cfform format= flash?
<cfsavecontent variable="doThis">
getURL("javascript:submitFilterFormOff()");
</cfsavecontent>
<script language="javascript">
function submitFilterFormOff() {
ColdFusion.Ajax.submitForm('filterForm', 'set_ind_filter_cookies.cfm', callbackac,
errorHandlerb);
}

function callbackac(text)
{
            ColdFusion.navigate('user_offline_assign_ind_filter_resultsnc_panel.cfm', 'divFilterResultsOff');
            return
}

function errorHandlerb(code, msg)
{
alert(msg);
}
</script>

I get the javascript to fire but then get an alert saying form ID not found

Thanks for any help
# Posted By Chris | 12/2/08 10:58 AM
Raymond Camden's Gravatar No idea, but once again I'll echo my recommendation to avoid Flash Forms and just use 'real' Flex.
# Posted By Raymond Camden | 12/2/08 11:04 AM
Gavy's Gravatar Hi Ray! I am using the Same Stuff as you but i did get any relevant output.

does this console.log works only with firefox or with all browsers
# Posted By Gavy | 12/17/08 12:24 AM
Andy Sandefer's Gravatar You need firebug (A very awesome firefox add-on)

http://getfirebug.com/
# Posted By Andy Sandefer | 12/17/08 8:39 AM