Andrew asks:
I hope you can help me. I come from an ASP.NET background and am moving across to ColdFusion. In .net there is a function called isPostBack() which came in very useful. I am now finding a need for this functionality within the Coldfusion environment so that certain blocks of code are only executed while the page is loading for the first time.
First off, I'm happy to welcome you to the ColdFusion community. We are a rowdy, but generally fun, bunch of geeks. We are known for being passionate about our language and emptying the beer kegs at conferences. I think you will find life much more fun here!
So I had to do a bit of digging, but I found that Andrew was a bit off on his description. isPostBack in .Net is run when a form is posted, not when a page is loaded. However in further emails with him he told me he was interested in both.
There is nothing inherit to ColdFusion that will, by itself, tell you if a form has been posted. You can check for a form post in a variety of ways though.
First, ColdFusion automatically populates a form field named fieldnames when a form is posted. This is a list of all form values. So one simple method to see if a form has been posted would be:
<cfif isDefined("form.fieldNames") and len(form.fieldNames)>
This will check to see if the value even exists and if it has something in it. I find that a bit long though. I think most people simply check for the existence of a particular form field. I will often check the name of the submit button. Given:
<input type="submit" name="save" value="Engage!">
You can do this to look for the submission:
<cfif isDefined("form.save")>
You can also treat the Form as a structure and check for either an empty struct or a particular key:
<cfif not isStructEmpty(form)>
or...
<cfif structKeyExists(form, "save")>
Obviously each of these could be reversed to check for a form not being submitted. One example:
<cfif not structKeyExists(form, "save")>
You could get really technical and dig into the headers. If you run getHTTPRequestData when a form post is submitted, the method will return POST as opposed to GET. That is probably going a bit too far thought.
Archived Comments
good options, but i usually just go with <cfif NOT isStructEmpty( Form )>. then i don't have to worry about giving my submit button a certain name.
You can also pick the request method (GET or POST) out of the cgi scope: cgi.REQUEST_METHOD
@Andrew,
You should really check out the coop library found at
coop.riaforge.org
John Farrar created this library and one of the things we support
is callbacks so you can set blocks of code to run (1) when the page
first loads,(2) every time the page loads, and (3) OnPostBack which
is fired whenever a form submission occurs.
We also support a style of coding with COOP that is somewhat similar to the codebehind pages in .net.
You can contact me at the following email with more questions, or for an updated copy of the library which we are saving to publicly release at CFUnited, and we are very glad to give people a walkthrough demo of COOP if you are interested:
timothyfarrar at sosensible.com
Hope you find this helpful,
Timothy Farrar
wish i was coming from a .NET backround :-) it would be like learning the greatest web language all over again!
@ChrisH - I will often use both a save and a cancel button on a form, so I need to check for the name.
I always use structkeyexists(form,"fieldnames") -- that one will always be there and it won't puke if someone loads the page directly so no form var exists.
For readability I generally use the StructKeyExists method you mentioned:
<cfif structKeyExists(form, "submit")>
<!--- Process Form --->
<cfelse>
<!--- On First Load --->
</cfif>
It's simple, short and reliable.
I name my submit button "submit" for consistency, even if the button value is something different like "save" or "update".
(Just remember not to cfparam the submit button when you're param'ing default values for the form.)
BTW, Thanks having the refresher every once in a while. Helps new folks and reminds us of the alternative ways to get the job done. :-)
I almost never use the submit button as the tested field value, as some browser do not send that value unless you specifically click on the submit button. So, if someone fills in a text field and hits their return key, the form submits, but your logic is never triggered because your submit button name is not part of the form structure.
@Dean: Which browsers? I'd like to do some testing on that.
Specifically, IE. I just ran this test on IE 7 and if you just click in the test field and hit return, the form scope does not contain the button value. Hopefully, my code will go through.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Form Submit Test</title>
</head>
<body>
<form action="formtest.cfm" id="formtest" name="formtest" method="POST">
<label for="textField">This is a text field</label><br />
<input type="text" id="textField" name="textField" /><br />
<input type="submit" id="btnSubmit" name="btnSubmit" value="Click Me!" />
</form>
<cfdump var="#form#">
</body>
</html>
Re: naming submit buttons, I don't do it either for reasons similar to Dean's. I recently got burned by that:
<input type="image" name="submit"> in IE does NOT result in a form.submit variable. IE sends data as "submit.x" and "submit.y" for the location of the click, but does not send a normal "submit" variable.
I know in the past I've run into other situations like Dean mentions where hitting "enter" wouldn't send the var. Don't remember specifics; I found my solution back in the 4.0 browser days and haven't had to deal with it since.
My solution is to always have a hidden form field "act" that identifies the form being submitted, and I check for that.
Of the solutions outlined so far, Ray's original form.fieldnames and isStructEmpty( Form ) are the most "built-in" and don't require changing your forms.
Good points on the 'missing' and .x .y stuff. That has burned me before as well.
I'm not sure why I asked... It's ALWAYS IE. :-(
I just noticed a typo: StructIsEmpty(form) rather than isStructEmpty(form).
---
I tested the methods above in IE 6, IE 7, Firefox 3, Chrome 1, and Safari 4 for Windows:
1) structFormEmpty(form) fails IF you cfparam any form fields.
2) To my dismay, IE 6 & 7 fails structKeyExists(form, "submit") if you press enter.
3) isDefined("form.fieldNames") works in all tested browsers with both enter and click submit. It appears to be the least intrusive method.
4) Testing for a known field other than submit, that was not cfparam'd also works fine.
Yes what Dean mentioned has caught me before too.
Also when just checking for form submission take into account the number of forms on a page. Maybe a search form and an email news letter subscribe form. Both of these forms can commonly be found on the same page. A good rule of thumb there is never make them submit to the same page. But when working on older sites you never know what you may run into..
I know ive dealt in IE with a form with one field and a submit button and the fields arent sent when you click the enter key to submit the form. if i have more than one field in the form, and click enter, then the submit button passes.
FF doesnt have this problem in my quick tests.
Another way is to just check the request method. This is what we use in our form post backs, something like:
<cfif CGI.Request_Method EQ "POST" >
... do post stuff here ...
</cfif>