You Cannot Submit Non-Rendered Forms
The other night, at Rob Gonda's NYCFUG presentation, we were talking about jQuery and AJAX and I wondered if a non-rendered Form element could be submitted. By that, I mean a Form node that existed in memory but was not actually part of the rendered page's document object model (DOM). See this demo if you are not sure what I mean:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Non-Rendered Form Submission</title>
<script type="text/javascript" src="jquery-1.2.3.pack.js"></script>
<script type="text/javascript">
function SubmitForm(){
var jForm = $(
"<form action='test.cfm' method='post'>" +
"<input type='hidden' name='test' value='Cool!'>" +
"</form>"
);
// Submit the form.
jForm.submit();
}
</script>
</head>
<body>
<h1>
Non-Rendered Form Submission
</h1>
<form>
<input
type="button"
value="Submit Non-Rendered Form"
onclick="SubmitForm()"
/>
</form>
</body>
</html>
As you can see above, when you click on the button, the SubmitForm() method is triggered. This method then creates an in-memory Form node with nested input value using jQuery and tries to submit it. On the server, I have the form submitting to this page to see if it worked:
<!--- Param the form variable. --->
<cfparam name="FORM.test" type="string" default="{NULL}" />
<!---
Add the form value to the log file so that we can
see what the form file is actually submitting.
--->
<cffile
action="append"
file="#ExpandPath( './debug.txt' )#"
output="#FORM.test#"
addnewline="true"
/>
Well, the long and short story is that it didn't work. I tried it in FireFox as well as Internet Explorer 7. Nothing. Oh well, just a quick experiment.
Want to use code from this post? Check out the license.
Reader Comments
Also, FYI, if you put this line in right before the submit:
$( "body" ).append( jForm );
The form does get attached to the body and the submission does work (but forwards the user's page to the test.cfm).
Isn't $("whatever") short for document.getElementById("whatever")?
If so, you're trying to get an id="<form ...", which doesn't exist, of course.
I kind of like the idea behind it though - you could create a form quickly and then submit it. I'm not sure why I'd use it, but the possibility of doing so is rather exciting.
I also think using the term "in memory form" with the explanation "I mean a Form node that existed in memory" is confusing. I had no idea what you meant until I saw the example. =)
@Sammy,
The $() constructor in jQuery can be a CSS and ID selector (as you have demonstrated); however, if presented with what it sees as HTML then it will create those nodes on the fly and return them in a jQuery object. This is why the example works IF You first append the jForm object to the BODY tag.
I thought it would be cool to be maybe be able to upload files using this kind of hidden form post.
Ben,
Thanks for the clarification. Gotta love the single responsibility principle. =)
Gotta love jQuery :) I guess you could call that "$" a factory method?
I actually don't see the problem. Can you present me with an example of when you can't add the form to the DOM?
@nitro2k01,
I am not worries about submitting a form once the FORM is attached to the DOM, that is standard. I wanted to see if you could submit a form that was not part of the DOM and therefore, not interacting with the page directly or forwarding the user to the action page.
Exactly. Even if it's an interesting experiment I don't see a good reason not to interact with the DOM. (Especially not when the form is to be submitted, so that the DOM is destroyed anyway)
Ben, I don't really see a need to submit a form that we never rendered, but just like you mentioned in the first comment, once you append the form to the body it works in every browser.
The case where I usually need that is when I add entire forms with an Ajax call and need the user to be able to submit them, and it works...
@Rob,
It was just an experiment :) I am not sure it would ever be useful. However, after you said in the presentation that files could not be uploaded via AJAX, I thought maybe if an non-rendered form could be submitted, you could possibly submit files this way, behind the scenes.
@Ben
The common design pattern for doing file uploads without blocking user interaction with the page is to use a form that's action targets a hidden iframe, or use a form inside a hidden iframe and call it's submit().
@Elliott,
Yeah, I think that is the way to go.
Why use a form like that at all anyways? With JQuery you can simply send an HTTP request (e.g. POST) directly to the server. You can do this various ways, including the serialization of an existing form, or using JSON to represent the data structure.
It's one of those things that's good to know, I suppose.
@Shayne,
In his presentation, Rob was saying that you could not send file data since AJAX style submits can only sent textual data. I figured, if you could submit a non-rendered form, you could also submit a non-rendered file input box. It was just a thought....
@Ben
Hrm ... I can't say I've personally achieved this, that is to upload file data over AJAX, but I am curious as to why it wouldn't be possible - it seems as if a company I know of does exactly that with their accounting software they've developed.
If I concede to that possibility it might not be possible - I'd presume you could accomplish this "asynchronous file upload" by using a hidden IFRAME and using it as the target for the FORM. Google Maps was initially based off this pseudo-asynchronous "AJAX like" approach. In fact our warehouse management system uses this method too and works like a charm.
@Shayne,
Yes, I believe all that you can do.
@Ben,
You commented this morning: "I guess you could call that "$" a factory method?" In fact, the jQuery documentation refers to $() as a factory method.
And since it returns an instance of the jQuery class and doesn't require the "new" operator, I see no reason to disagree!
On my way home this night, I came to think of a perfectly good reason why you can't post non-rendered forms. Before a form is added to the DOM the engine has no clue which document it belongs to. Is this a problem? When there are multiple frames or windows, it is a problem since the newly created form could be added anywhere in the DOM tree. Even if the object was created a in one frame it could theoretically be added to another frame or or newly opened window.
From that point of view I think it's correct that an orphan form can't be submitted.
The simplest way to post a form without changing the URL of the viewing page is to create an iframe that is positioned out of view and setting the target of the form to it and then submitting it.
@Justin,
This is true, especially when you need to upload a File - something that cannot be done with AJAX technology exclusively.