I was trying to use a cfform inside a cflayoutarea. What I wanted to do was have the page that processes the submitted form redirect back to the original form (using ajax, still inside of the cflayoutarea) if the user entered something invalid.
It seemed strange to me that I couldn't use cflocation to display the original form within the ajax request. If I did, i'd get a form full of bind errors, saying that various form objects couldn't be found.
Instead, I had to cfinclude the page with the form on it, followed by a cfabort, on the processign page, to achieve the same thing. Does that seem strange to you or do you think there's a valid reason for that kind of behaviour?
So there are a few things in play here. First, let’s forget about AJAX for a second. In general, when I do form validation as you describe above, I generally do not cflocate back to the form. Outside of MVC style applications, my form will post to itself. The validation is done on top, and if anything is wrong, I simply create a list of problems. The problem with cflocating back to the form is that you lose the FORM values the user had entered. If a form had 10 items and only 1 was wrong, you are going to really tick off users if they lose the rest of their form values. In pseudo-code, my form (again, outside of a MVC framework) will work like so:
if a form was submitted:
check each field and make a list of errors
if no errors, save the data and send the user to a listing page
if an error occurred, display it
display form with a post to self </code>
So that being said, you said you used cfform inside of a layoutarea with a cflocation on error. I made a quick demo like so:
<cfif structKeyExists(form, “submit”)> <cfif not len(trim(form.name))> <cflocation url=”test.cfm?bad=1”> </cfif> </cfif> <cfif structKeyExists(url, “bad”)> <p>Bad!</p> </cfif> <cfform name=”test”> <cfinput name=”name” type=”text”> <cfinput name=”submit” type=”submit”> </cfform>
If you run this and hit submit without filling a value, you will indeed get an error. Removing the cflocation doesn’t help much either:
<cfif structKeyExists(form, “submit”)> <cfif not len(trim(form.name))> <p>Bad!</p> </cfif> </cfif> <cfform name=”test”> <cfinput name=”name” type=”text”> <cfinput name=”submit” type=”submit”> </cfform>
Which results in, after a few clicks:
What I’d recommend is a simpler approach. Move the form itself into a new file and switch your tab to:
<cflayoutarea title="foo" source="test.cfm">
In the form you can keep things nice and simple:
<cfif structKeyExists(form, "submit")>
<cfset variables.bad = 1>
<cfif structKeyExists(variables, "bad")>
<cfinput name="name" type="text">
<cfinput name="submit" type="submit">
If you do this, though, you have to modify the original page with the tags to include an ajaximport call:
Altogether now - the form now will automatically do an AJAX post to itself (this just happens automatically with cfform in CF8 when used inside an ajax-based container) and correctly handle the error. (Note, you can also consider using ColdFusion.Ajax.submitForm, I have a few blog entries on that.)