I know that xhtml doesn't support nested form tags and I have already read other answers
here in * regarding this subject, but I still haven't figured out an elegant solution to the problem.
我知道xhtml不支持嵌套表单标记,并且我已经在*中阅读了关于这个主题的其他答案,但是我仍然没有找到一个优雅的解决方案。
Some say you don't need it and that they can't think of a scenario were this would be needed. Well, personally I can't think of a scenario that I HAVEN'T needed it.
有些人说你不需要它,他们想不出一个场景是需要的。就我个人而言,我想不出一个我不需要的场景。
Let's see a very simple example:
让我们看一个非常简单的例子:
You are making a blog app and you have a form with some fields for creating a new post and a toolbar with "actions" like "Save", "Delete", "Cancel".
你正在制作一个博客应用程序,你有一个表单,里面有一些用于创建新文章的字段,还有一个带有“动作”的工具栏,比如“保存”、“删除”、“取消”。
<form
action="/post/dispatch/too_bad_the_action_url_is_in_the_form_tag_even_though_conceptually_every_submit_button_inside_it_may_need_to_post_to_a_diffent_distinct_url"
method="post">
<input type="text" name="foo" /> <!-- several of those here -->
<div id="toolbar">
<input type="submit" name="save" value="Save" />
<input type="submit" name="delete" value="Delete" />
<a href="/home/index">Cancel</a>
</div>
</form>
Our objective is to write the form in a way that doesn't require javascript, just plain old html form and submit buttons.
我们的目标是以一种不需要javascript的方式编写表单,只需要简单的旧html表单和提交按钮。
Since the action url is defined in the Form tag and not in each individual submit button, our only option is to post to a generic url and then start "if...then...else" to determine the name of the button that was submitted. Not very elegant, but our only choice, since we don't want to rely on javascript.
由于操作url是在表单标记中定义的,而不是在每个单独的提交按钮中定义的,所以我们唯一的选择是将其发布到一个通用url,然后开始“if…then…”else“用于确定提交的按钮的名称。不是很优雅,但这是我们唯一的选择,因为我们不想依赖javascript。
The only problem is that pressing "Delete", will submit ALL the form fields on the server even though the only thing needed for this action is a Hidden input with the post-id. Not very big deal in this small example, but I have forms with hundreds (so to speak) of fields and tabs in my LOB applications that (because of requirements) have to submit everything in one-go and in any case this seems very inefficient and a waste. If form nesting was supported, I would at least be able to wrap the "Delete" submit button inside it's own form with only the post-id field.
唯一的问题是按下“Delete”,将提交服务器上的所有表单字段,尽管此操作所需的惟一内容是使用post-id的隐藏输入。在这个小示例中并不是什么大问题,但是我的LOB应用程序中有数百个(可以说)字段和制表符的表单(由于需求)必须一次性提交所有内容,无论如何,这似乎非常低效和浪费。如果支持表单嵌套,那么我至少可以将“Delete”提交按钮包装在它自己的表单中,只使用后id字段。
You may say "Just implement the "Delete" as a link instead of submit". This would be wrong in so many levels, but most importantly because Side-effect actions like "Delete" here, should never be a GET request.
你可能会说“只是把”删除“作为一个链接而不是提交”。这在很多层面上都是错误的,但最重要的是,在这里“删除”这样的副作用,不应该是一个GET请求。
So my question (particularly to those that say they haven't needed form nesting) is What do YOU do? Is there any elegant solution that I'm missing or the bottom line is really "Either require javascript or submit everything"?
所以我的问题(尤其是那些说他们不需要表单嵌套的人)是你该怎么做?我是否遗漏了什么优雅的解决方案,或者底线是“要么需要javascript,要么提交所有内容”?
16 个解决方案
#1
52
I would implement this exactly as you described: submit everything to the server and do a simple if/else to check what button was clicked.
我将按照您所描述的那样实现这一点:将所有内容提交给服务器,并执行一个简单的if/else来检查所单击的按钮。
And then I would implement a Javascript call tying into the form's onsubmit event which would check before the form was submitted, and only submit the relevant data to the server (possibly through a second form on the page with the ID needed to process the thing as a hidden input, or refresh the page location with the data you need passed as a GET request, or do an Ajax post to the server, or...).
然后我将实现一个Javascript调用绑定到表单的onsubmit事件将检查在表单被提交之前,只有向服务器提交相关数据(可能通过ID的第二种形式在页面上需要处理的事情作为一个隐藏的输入,或者刷新页面位置的数据需要通过GET请求,或者做一个Ajax post到服务器,或……)。
This way the people without Javascript are able to use the form just fine, but the server load is offset because the people who do have Javascript are only submitting the single piece of data needed. Getting yourself focused on only supporting one or the other really limits your options unnecessarily.
这样,没有Javascript的人就可以很好地使用表单,但是服务器负载会被抵消,因为拥有Javascript的人只提交所需的单个数据。让自己只专注于支持其中一个或另一个真的会限制你不必要的选择。
Alternatively, if you're working behind a corporate firewall or something and everybody has Javascript disabled, you might want to do two forms and work some CSS magic to make it look like the delete button is part of the first form.
或者,如果您在公司防火墙或其他地方工作,并且每个人都禁用了Javascript,那么您可能需要执行两个表单,并使用一些CSS魔法使其看起来像删除按钮是第一个表单的一部分。
#2
172
I know this is an old question, but HTML5 offers a couple new options.
我知道这是一个老问题,但是HTML5提供了一些新的选项。
The first is to separate the form from the toolbar in the markup, add another form for the delete action, and associate the buttons in the toolbar with their respective forms using the form
attribute.
第一个是将表单与标记中的工具栏分隔开,为delete操作添加另一个表单,并使用form属性将工具栏中的按钮与相应的表单关联起来。
<form id="saveForm" action="/post/dispatch/save" method="post">
<input type="text" name="foo" /> <!-- several of those here -->
</form>
<form id="deleteForm" action="/post/dispatch/delete" method="post">
<input type="hidden" value="some_id" />
</form>
<div id="toolbar">
<input type="submit" name="save" value="Save" form="saveForm" />
<input type="submit" name="delete" value="Delete" form="deleteForm" />
<a href="/home/index">Cancel</a>
</div>
This option is quite flexible, but the original post also mentioned that it may be necessary to perform different actions with a single form. HTML5 comes to the rescue, again. You can use the formaction
attribute on submit buttons, so different buttons in the same form can submit to different URLs. This example just adds a clone method to the toolbar outside the form, but it would work the same nested in the form.
这个选项非常灵活,但是最初的帖子也提到,可能需要用一个表单执行不同的操作。HTML5再次拯救了我们。您可以在submit按钮上使用formaction属性,因此相同表单中的不同按钮可以提交到不同的url。这个示例只是向窗体外部的工具栏添加了一个克隆方法,但它将在窗体中使用相同的嵌套。
<div id="toolbar">
<input type="submit" name="clone" value="Clone" form="saveForm"
formaction="/post/dispatch/clone" />
</div>
http://www.whatwg.org/specs/web-apps/current-work/#attributes-for-form-submission
http://www.whatwg.org/specs/web-apps/current-work/ attributes-for-form-submission
The advantage of these new features is that they do all this declaratively without JavaScript. The disadvantage is that they are not supported on older browsers, so you'd have to do some polyfilling for older browsers.
这些新特性的优点是,它们都是声明式的,不使用JavaScript。缺点是它们不支持旧浏览器,因此必须对旧浏览器进行一些多填充。
#3
16
can you have the forms side by side on the page, but not nested. then use CSS to make all the buttons line up pretty?
可以在页面上并排显示表单,但不嵌套吗?然后使用CSS使所有的按钮对齐?
<form method="post" action="delete_processing_page">
<input type="hidden" name="id" value="foo" />
<input type="submit" value="delete" class="css_makes_me_pretty" />
</form>
<form method="post" action="add_edit_processing_page">
<input type="text" name="foo1" />
<input type="text" name="foo2" />
<input type="text" name="foo3" />
...
<input type="submit" value="post/edit" class="css_makes_me_pretty" />
</form>
#4
13
HTML5 has an idea of "form owner" - the "form" attribute for input elements. It allows to emulate nested forms and will solve the issue.
HTML5有一个“表单所有者”的概念——输入元素的“表单”属性。它允许模拟嵌套的表单,并将解决这个问题。
#5
11
Kind of old topic, but this one might be useful for someone:
这是个老话题,但这个可能对某些人有用:
As someone mentioned above - you can use dummy form. I had to overcome this issue some time ago. At first I totally forgot about this HTML restriction and just added the nested forms. Result was interesting - I lost my first form from the nested. Then it turned out to be some kind of a "trick" to simply add a dummy form (that will be removed from the browser) before the actual nested forms.
正如上面提到的,你可以使用虚拟形式。不久前我不得不克服这个问题。起初,我完全忘记了这个HTML限制,只是添加了嵌套的表单。结果很有趣——我从嵌套中丢失了第一个表单。然后,在实际的嵌套表单之前添加一个虚拟表单(将从浏览器中删除),结果证明是某种“技巧”。
In my case it looks like this:
我的情况是这样的:
<form id="Main">
<form></form> <!--this is the dummy one-->
<input...><form id="Nested 1> ... </form>
<input...><form id="Nested 1> ... </form>
<input...><form id="Nested 1> ... </form>
<input...><form id="Nested 1> ... </form>
......
</form>
Works fine with Chrome, FireFox and Safari. IE up to 9 (not sure about 10) and Opera does not detect parameters in the main form. The $_REQUEST global is empty, regardless of the inputs. Inner forms seems to work fine everywhere.
适用于Chrome, FireFox和Safari浏览器。IE到9(不确定是10)和Opera不检测主要形式的参数。$_REQUEST全局变量为空,不管输入是什么。内在的形式似乎在任何地方都适用。
Haven't tested another suggestion described here - fieldset around nested forms.
还没有测试这里描述的另一个建议——围绕嵌套表单的fieldset。
EDIT: Frameset didn't work! I simply added Main form after the others (no more nested forms) and used jQuery's "clone" to duplicate inputs in the form on button click. Added .hide() to each of the cloned inputs to keep layout unchanged and now it works like a charm.
编辑:框架没有工作!我只是在其他表单之后添加了主表单(不再嵌套表单),并使用jQuery的“克隆”在按钮单击时复制表单中的输入。将.hide()添加到每个克隆输入中,以保持布局不变,现在它就像一个魔咒一样工作。
#6
4
I think Jason's right. If your "Delete" action is a minimal one, make that be in a form by itself, and line it up with the other buttons so as to make the interface look like one unified form, even if it's not.
我认为杰森是对的。如果你的“删除”操作是一个最小的操作,那就把它变成一个表单,并将它与其他按钮对齐,使界面看起来像一个统一的表单,即使它不是。
Or, of course, redesign your interface, and let people delete somewhere else entirely which doesn't require them to see the enormo-form at all.
或者,当然,重新设计你的界面,让人们完全删除其他地方,而不需要他们看到enormo-form。
#7
2
One way I would do this without javascript would be to add a set of radio buttons that define the action to be taken:
在没有javascript的情况下,我可以添加一组单选按钮来定义要执行的操作:
- Update
- 更新
- Delete
- 删除
- Whatever
- 无论
Then the action script would take different actions depending on the value of the radio button set.
然后操作脚本将根据单选按钮集的值采取不同的操作。
Another way would be to put two forms on the page as you suggested, just not nested. The layout may be difficult to control though:
另一种方法是按照您的建议在页面上放置两个表单,而不是嵌套。但是布局可能很难控制:
<form name="editform" action="the_action_url" method="post"> <input type="hidden" name="task" value="update" /> <input type="text" name="foo" /> <input type="submit" name="save" value="Save" /> </form> <form name="delform" action="the_action_url" method="post"> <input type="hidden" name="task" value="delete" /> <input type="hidden" name="post_id" value="5" /> <input type="submit" name="delete" value="Delete" /> </form>
Using the hidden "task" field in the handling script to branch appropriately.
使用处理脚本中隐藏的“任务”字段进行适当的分支。
#8
1
Use an iframe
for the nested form. If they need to share fields, then... it's not really nested.
使用嵌套表单的iframe。如果他们需要共享字段,那么……这真的不是嵌套。
#9
1
My solution is to have the buttons call JS functions which write and then submit forms outwith the main form
我的解决方案是让按钮调用JS函数,这些函数编写表单,然后用主表单提交表单
<head>
<script>
function removeMe(A, B){
document.write('<form name="removeForm" method="POST" action="Delete.php">');
document.write('<input type="hidden" name="customerID" value="' + A + '">');
document.write('<input type="hidden" name="productID" value="' + B + '">');
document.write('</form>');
document.removeForm.submit();
}
function insertMe(A, B){
document.write('<form name="insertForm" method="POST" action="Insert.php">');
document.write('<input type="hidden" name="customerID" value="' + A + '">');
document.write('<input type="hidden" name="productID" value="' + B + '">');
document.write('</form>');
document.insertForm.submit();
}
</script>
</head>
<body>
<form method="POST" action="main_form_purpose_page.php">
<input type="button" name="remove" Value="Remove" onclick="removeMe('$customerID','$productID')">
<input type="button" name="insert" Value="Insert" onclick="insertMe('$customerID','$productID')">
<input type="submit" name="submit" value="Submit">
</form>
</body>
#10
0
Well, if you submit a form, browser also sends a input submit name and value. So what yo can do is
如果你提交一个表单,浏览器也会发送一个输入提交名和值。所以你能做的就是
<form
action="/post/dispatch/too_bad_the_action_url_is_in_the_form_tag_even_though_conceptually_every_submit_button_inside_it_may_need_to_post_to_a_diffent_distinct_url"
method="post">
<input type="text" name="foo" /> <!-- several of those here -->
<div id="toolbar">
<input type="submit" name="action:save" value="Save" />
<input type="submit" name="action:delete" value="Delete" />
<input type="submit" name="action:cancel" value="Cancel" />
</div>
</form>
so on server side you just look for parameter that starts width string "action:" and the rest part tells you what action to take
因此,在服务器端,您只需查找开始宽度字符串“action:”的参数,其余部分将告诉您采取什么操作
so when you click on button Save browser sends you something like foo=asd&action:save=Save
当你点击按钮时保存浏览器会发送一些东西给你,比如foo=asd&action: Save =Save
#11
0
This discussion is still of interest to me. Behind the original post are "requirements" which the OP seems to share - i.e. a form with backwards compatibility. As someone whose work at time of writing must sometimes support back to IE6 (and for years to come), I dig that.
我对这次讨论仍感兴趣。在最初的帖子后面是OP似乎共享的“需求”——即具有向后兼容性的表单。作为一个在写作时工作的人有时必须支持IE6(并且在未来的几年里),我很喜欢。
Without pushing the framework (all organisations are going to want to reassure themselves on compatibility/robustness, and I'm not using this discussion as justification for the framework), the Drupal solutions to this issue are interesting. Drupal is also directly relevant because the framework has had a long time policy of "it should work without Javascript (only if you want)" i.e. the OP's issue.
如果不推动框架(所有组织都希望在兼容性/健壮性上让自己放心,而且我也不会用这个讨论作为框架的理由),Drupal解决这个问题的解决方案就很有趣。Drupal也是直接相关的,因为这个框架有一个长期的策略,即“它应该在没有Javascript的情况下工作(如果你愿意的话)”,也就是OP的问题。
Drupal uses it's rather extensive form.inc functions to find the triggering_element (yes, that's the name in code). See the bottom of the code listed on the API page for form_builder (if you'd like to dig into details, source is recommended - drupal-x.xx/includes/form.inc). The builder uses automatic HTML attribute generation and, via that, can on return detect which button was pressed, and act accordingly (these can be set up to run separate processes too).
Drupal使用非常广泛的形式。inc函数查找triggering_element(是的,这是代码中的名称)。请参阅form_builder的API页面上列出的代码的底部(如果您想深入了解细节,建议使用源代码——drupal-x.xx/includes/form.inc)。构建器使用自动生成HTML属性,并通过它返回检测按了哪个按钮,并相应地执行(这些也可以设置为运行单独的进程)。
Beyond the form builder, Drupal splits data 'delete' actions into separate urls/forms, likely for the reasons mentioned in the original post. This needs some sort of search/listing step (groan another form!, but is user-friendly) as a preliminary. But this has the advantage of eliminating the "submit everything" issue. The big form with the data is used for it's intended purpose, data creation/updating (or even a 'merge' action).
在表单构建器之外,Drupal将数据“delete”操作拆分为单独的url /表单,这可能是由于原始post中提到的原因。这需要某种搜索/列出步骤(呻吟另一个表单!,但对用户友好)作为初步。但这样做的好处是可以消除“提交一切”问题。带有数据的大表单用于其预期目的、数据创建/更新(甚至是“合并”操作)。
In other words, one way of working round the problem is to devolve the form into two, then the problem vanishes (and the HTML methods can be corrected through a POST too).
换句话说,解决这个问题的一种方法是将表单分成两部分,然后问题就消失了(HTML方法也可以通过POST进行纠正)。
#12
-1
If you really don't want to use multiple forms (as Jason sugests), then use buttons and onclick handlers.
如果您真的不想使用多个表单(如Jason sugests),则使用按钮和onclick处理程序。
<form id='form' name='form' action='path/to/add/edit/blog' method='post'>
<textarea name='message' id='message'>Blog message here</textarea>
<input type='submit' id='save' value='Save'>
</form>
<button id='delete'>Delete</button>
<button id='cancel'>Cancel</button>
And then in javascript (I use jQuery here for easyness) (even though it is pretty overkill for adding some onclick handlers)
然后在javascript中(我在这里使用jQuery来简化)(尽管添加onclick处理程序有点过分)
$('#delete').click( function() {
document.location = 'path/to/delete/post/id';
});
$('#cancel').click( function() {
document.location = '/home/index';
});
Also I know, this will make half the page not work without javascript.
我也知道,这将使页面的一半不能没有javascript。
#13
-1
In response to a question posted by Yar in a comment to his own answer, I present some JavaScript which will resize an iframe. For the case of a form button, it is safe to assume the iframe will be on the same domain. This is the code I use. You will have to alter the maths/constants for your own site:
在回答Yar对自己的回答发表评论时,我提出了一些可以调整iframe大小的JavaScript。对于表单按钮,可以安全地假设iframe将位于相同的域中。这是我使用的代码。你必须改变你自己网站的数学/常数:
function resizeIFrame(frame)
{
try {
innerDoc = ('contentDocument' in frame) ? frame.contentDocument : frame.contentWindow.document;
if('style' in frame) {
frame.style.width = Math.min(755, Math.ceil(innerDoc.body.scrollWidth)) + 'px';
frame.style.height = Math.ceil(innerDoc.body.scrollHeight) + 'px';
} else {
frame.width = Math.ceil(innerDoc.body.scrollWidth);
frame.height = Math.ceil(innerDoc.body.scrollHeight);
}
} catch(err) {
window.status = err.message;
}
}
Then call it like this:
然后这样称呼它:
<iframe ... frameborder="0" onload="if(window.parent && window.parent.resizeIFrame){window.parent.resizeIFrame(this);}"></iframe>
#14
-1
I just came up with a nice way of doing it with jquery.
我刚刚想出了一种使用jquery的好方法。
<form name="mainform">
<div id="placeholder">
<div>
</form>
<form id="nested_form" style="position:absolute">
</form>
<script>
$(document).ready(function(){
pos = $('#placeholder').position();
$('#nested_form')
.css('left', pos.left.toFixed(0)+'px')
.css('top', pos.top.toFixed(0)+'px');
});
</script>
#15
-1
I went around the issue by including a checkbox depending on what form the person wanted to do. Then used 1 button to submit the whole form.
我通过包括一个复选框来解决这个问题,这取决于这个人想要做什么。然后使用1按钮提交整个表单。
#16
-2
Alternatively you could assign the form actiob on the fly...might not be the best solution, but sure does relieve the server-side logic...
或者,您可以动态地分配表单actiob……可能不是最好的解决方案,但肯定会减轻服务器端逻辑……
<form name="frm" method="post">
<input type="submit" value="One" onclick="javascript:this.form.action='1.htm'" />
<input type="submit" value="Two" onclick="javascript:this.form.action='2.htm'" />
</form>
#1
52
I would implement this exactly as you described: submit everything to the server and do a simple if/else to check what button was clicked.
我将按照您所描述的那样实现这一点:将所有内容提交给服务器,并执行一个简单的if/else来检查所单击的按钮。
And then I would implement a Javascript call tying into the form's onsubmit event which would check before the form was submitted, and only submit the relevant data to the server (possibly through a second form on the page with the ID needed to process the thing as a hidden input, or refresh the page location with the data you need passed as a GET request, or do an Ajax post to the server, or...).
然后我将实现一个Javascript调用绑定到表单的onsubmit事件将检查在表单被提交之前,只有向服务器提交相关数据(可能通过ID的第二种形式在页面上需要处理的事情作为一个隐藏的输入,或者刷新页面位置的数据需要通过GET请求,或者做一个Ajax post到服务器,或……)。
This way the people without Javascript are able to use the form just fine, but the server load is offset because the people who do have Javascript are only submitting the single piece of data needed. Getting yourself focused on only supporting one or the other really limits your options unnecessarily.
这样,没有Javascript的人就可以很好地使用表单,但是服务器负载会被抵消,因为拥有Javascript的人只提交所需的单个数据。让自己只专注于支持其中一个或另一个真的会限制你不必要的选择。
Alternatively, if you're working behind a corporate firewall or something and everybody has Javascript disabled, you might want to do two forms and work some CSS magic to make it look like the delete button is part of the first form.
或者,如果您在公司防火墙或其他地方工作,并且每个人都禁用了Javascript,那么您可能需要执行两个表单,并使用一些CSS魔法使其看起来像删除按钮是第一个表单的一部分。
#2
172
I know this is an old question, but HTML5 offers a couple new options.
我知道这是一个老问题,但是HTML5提供了一些新的选项。
The first is to separate the form from the toolbar in the markup, add another form for the delete action, and associate the buttons in the toolbar with their respective forms using the form
attribute.
第一个是将表单与标记中的工具栏分隔开,为delete操作添加另一个表单,并使用form属性将工具栏中的按钮与相应的表单关联起来。
<form id="saveForm" action="/post/dispatch/save" method="post">
<input type="text" name="foo" /> <!-- several of those here -->
</form>
<form id="deleteForm" action="/post/dispatch/delete" method="post">
<input type="hidden" value="some_id" />
</form>
<div id="toolbar">
<input type="submit" name="save" value="Save" form="saveForm" />
<input type="submit" name="delete" value="Delete" form="deleteForm" />
<a href="/home/index">Cancel</a>
</div>
This option is quite flexible, but the original post also mentioned that it may be necessary to perform different actions with a single form. HTML5 comes to the rescue, again. You can use the formaction
attribute on submit buttons, so different buttons in the same form can submit to different URLs. This example just adds a clone method to the toolbar outside the form, but it would work the same nested in the form.
这个选项非常灵活,但是最初的帖子也提到,可能需要用一个表单执行不同的操作。HTML5再次拯救了我们。您可以在submit按钮上使用formaction属性,因此相同表单中的不同按钮可以提交到不同的url。这个示例只是向窗体外部的工具栏添加了一个克隆方法,但它将在窗体中使用相同的嵌套。
<div id="toolbar">
<input type="submit" name="clone" value="Clone" form="saveForm"
formaction="/post/dispatch/clone" />
</div>
http://www.whatwg.org/specs/web-apps/current-work/#attributes-for-form-submission
http://www.whatwg.org/specs/web-apps/current-work/ attributes-for-form-submission
The advantage of these new features is that they do all this declaratively without JavaScript. The disadvantage is that they are not supported on older browsers, so you'd have to do some polyfilling for older browsers.
这些新特性的优点是,它们都是声明式的,不使用JavaScript。缺点是它们不支持旧浏览器,因此必须对旧浏览器进行一些多填充。
#3
16
can you have the forms side by side on the page, but not nested. then use CSS to make all the buttons line up pretty?
可以在页面上并排显示表单,但不嵌套吗?然后使用CSS使所有的按钮对齐?
<form method="post" action="delete_processing_page">
<input type="hidden" name="id" value="foo" />
<input type="submit" value="delete" class="css_makes_me_pretty" />
</form>
<form method="post" action="add_edit_processing_page">
<input type="text" name="foo1" />
<input type="text" name="foo2" />
<input type="text" name="foo3" />
...
<input type="submit" value="post/edit" class="css_makes_me_pretty" />
</form>
#4
13
HTML5 has an idea of "form owner" - the "form" attribute for input elements. It allows to emulate nested forms and will solve the issue.
HTML5有一个“表单所有者”的概念——输入元素的“表单”属性。它允许模拟嵌套的表单,并将解决这个问题。
#5
11
Kind of old topic, but this one might be useful for someone:
这是个老话题,但这个可能对某些人有用:
As someone mentioned above - you can use dummy form. I had to overcome this issue some time ago. At first I totally forgot about this HTML restriction and just added the nested forms. Result was interesting - I lost my first form from the nested. Then it turned out to be some kind of a "trick" to simply add a dummy form (that will be removed from the browser) before the actual nested forms.
正如上面提到的,你可以使用虚拟形式。不久前我不得不克服这个问题。起初,我完全忘记了这个HTML限制,只是添加了嵌套的表单。结果很有趣——我从嵌套中丢失了第一个表单。然后,在实际的嵌套表单之前添加一个虚拟表单(将从浏览器中删除),结果证明是某种“技巧”。
In my case it looks like this:
我的情况是这样的:
<form id="Main">
<form></form> <!--this is the dummy one-->
<input...><form id="Nested 1> ... </form>
<input...><form id="Nested 1> ... </form>
<input...><form id="Nested 1> ... </form>
<input...><form id="Nested 1> ... </form>
......
</form>
Works fine with Chrome, FireFox and Safari. IE up to 9 (not sure about 10) and Opera does not detect parameters in the main form. The $_REQUEST global is empty, regardless of the inputs. Inner forms seems to work fine everywhere.
适用于Chrome, FireFox和Safari浏览器。IE到9(不确定是10)和Opera不检测主要形式的参数。$_REQUEST全局变量为空,不管输入是什么。内在的形式似乎在任何地方都适用。
Haven't tested another suggestion described here - fieldset around nested forms.
还没有测试这里描述的另一个建议——围绕嵌套表单的fieldset。
EDIT: Frameset didn't work! I simply added Main form after the others (no more nested forms) and used jQuery's "clone" to duplicate inputs in the form on button click. Added .hide() to each of the cloned inputs to keep layout unchanged and now it works like a charm.
编辑:框架没有工作!我只是在其他表单之后添加了主表单(不再嵌套表单),并使用jQuery的“克隆”在按钮单击时复制表单中的输入。将.hide()添加到每个克隆输入中,以保持布局不变,现在它就像一个魔咒一样工作。
#6
4
I think Jason's right. If your "Delete" action is a minimal one, make that be in a form by itself, and line it up with the other buttons so as to make the interface look like one unified form, even if it's not.
我认为杰森是对的。如果你的“删除”操作是一个最小的操作,那就把它变成一个表单,并将它与其他按钮对齐,使界面看起来像一个统一的表单,即使它不是。
Or, of course, redesign your interface, and let people delete somewhere else entirely which doesn't require them to see the enormo-form at all.
或者,当然,重新设计你的界面,让人们完全删除其他地方,而不需要他们看到enormo-form。
#7
2
One way I would do this without javascript would be to add a set of radio buttons that define the action to be taken:
在没有javascript的情况下,我可以添加一组单选按钮来定义要执行的操作:
- Update
- 更新
- Delete
- 删除
- Whatever
- 无论
Then the action script would take different actions depending on the value of the radio button set.
然后操作脚本将根据单选按钮集的值采取不同的操作。
Another way would be to put two forms on the page as you suggested, just not nested. The layout may be difficult to control though:
另一种方法是按照您的建议在页面上放置两个表单,而不是嵌套。但是布局可能很难控制:
<form name="editform" action="the_action_url" method="post"> <input type="hidden" name="task" value="update" /> <input type="text" name="foo" /> <input type="submit" name="save" value="Save" /> </form> <form name="delform" action="the_action_url" method="post"> <input type="hidden" name="task" value="delete" /> <input type="hidden" name="post_id" value="5" /> <input type="submit" name="delete" value="Delete" /> </form>
Using the hidden "task" field in the handling script to branch appropriately.
使用处理脚本中隐藏的“任务”字段进行适当的分支。
#8
1
Use an iframe
for the nested form. If they need to share fields, then... it's not really nested.
使用嵌套表单的iframe。如果他们需要共享字段,那么……这真的不是嵌套。
#9
1
My solution is to have the buttons call JS functions which write and then submit forms outwith the main form
我的解决方案是让按钮调用JS函数,这些函数编写表单,然后用主表单提交表单
<head>
<script>
function removeMe(A, B){
document.write('<form name="removeForm" method="POST" action="Delete.php">');
document.write('<input type="hidden" name="customerID" value="' + A + '">');
document.write('<input type="hidden" name="productID" value="' + B + '">');
document.write('</form>');
document.removeForm.submit();
}
function insertMe(A, B){
document.write('<form name="insertForm" method="POST" action="Insert.php">');
document.write('<input type="hidden" name="customerID" value="' + A + '">');
document.write('<input type="hidden" name="productID" value="' + B + '">');
document.write('</form>');
document.insertForm.submit();
}
</script>
</head>
<body>
<form method="POST" action="main_form_purpose_page.php">
<input type="button" name="remove" Value="Remove" onclick="removeMe('$customerID','$productID')">
<input type="button" name="insert" Value="Insert" onclick="insertMe('$customerID','$productID')">
<input type="submit" name="submit" value="Submit">
</form>
</body>
#10
0
Well, if you submit a form, browser also sends a input submit name and value. So what yo can do is
如果你提交一个表单,浏览器也会发送一个输入提交名和值。所以你能做的就是
<form
action="/post/dispatch/too_bad_the_action_url_is_in_the_form_tag_even_though_conceptually_every_submit_button_inside_it_may_need_to_post_to_a_diffent_distinct_url"
method="post">
<input type="text" name="foo" /> <!-- several of those here -->
<div id="toolbar">
<input type="submit" name="action:save" value="Save" />
<input type="submit" name="action:delete" value="Delete" />
<input type="submit" name="action:cancel" value="Cancel" />
</div>
</form>
so on server side you just look for parameter that starts width string "action:" and the rest part tells you what action to take
因此,在服务器端,您只需查找开始宽度字符串“action:”的参数,其余部分将告诉您采取什么操作
so when you click on button Save browser sends you something like foo=asd&action:save=Save
当你点击按钮时保存浏览器会发送一些东西给你,比如foo=asd&action: Save =Save
#11
0
This discussion is still of interest to me. Behind the original post are "requirements" which the OP seems to share - i.e. a form with backwards compatibility. As someone whose work at time of writing must sometimes support back to IE6 (and for years to come), I dig that.
我对这次讨论仍感兴趣。在最初的帖子后面是OP似乎共享的“需求”——即具有向后兼容性的表单。作为一个在写作时工作的人有时必须支持IE6(并且在未来的几年里),我很喜欢。
Without pushing the framework (all organisations are going to want to reassure themselves on compatibility/robustness, and I'm not using this discussion as justification for the framework), the Drupal solutions to this issue are interesting. Drupal is also directly relevant because the framework has had a long time policy of "it should work without Javascript (only if you want)" i.e. the OP's issue.
如果不推动框架(所有组织都希望在兼容性/健壮性上让自己放心,而且我也不会用这个讨论作为框架的理由),Drupal解决这个问题的解决方案就很有趣。Drupal也是直接相关的,因为这个框架有一个长期的策略,即“它应该在没有Javascript的情况下工作(如果你愿意的话)”,也就是OP的问题。
Drupal uses it's rather extensive form.inc functions to find the triggering_element (yes, that's the name in code). See the bottom of the code listed on the API page for form_builder (if you'd like to dig into details, source is recommended - drupal-x.xx/includes/form.inc). The builder uses automatic HTML attribute generation and, via that, can on return detect which button was pressed, and act accordingly (these can be set up to run separate processes too).
Drupal使用非常广泛的形式。inc函数查找triggering_element(是的,这是代码中的名称)。请参阅form_builder的API页面上列出的代码的底部(如果您想深入了解细节,建议使用源代码——drupal-x.xx/includes/form.inc)。构建器使用自动生成HTML属性,并通过它返回检测按了哪个按钮,并相应地执行(这些也可以设置为运行单独的进程)。
Beyond the form builder, Drupal splits data 'delete' actions into separate urls/forms, likely for the reasons mentioned in the original post. This needs some sort of search/listing step (groan another form!, but is user-friendly) as a preliminary. But this has the advantage of eliminating the "submit everything" issue. The big form with the data is used for it's intended purpose, data creation/updating (or even a 'merge' action).
在表单构建器之外,Drupal将数据“delete”操作拆分为单独的url /表单,这可能是由于原始post中提到的原因。这需要某种搜索/列出步骤(呻吟另一个表单!,但对用户友好)作为初步。但这样做的好处是可以消除“提交一切”问题。带有数据的大表单用于其预期目的、数据创建/更新(甚至是“合并”操作)。
In other words, one way of working round the problem is to devolve the form into two, then the problem vanishes (and the HTML methods can be corrected through a POST too).
换句话说,解决这个问题的一种方法是将表单分成两部分,然后问题就消失了(HTML方法也可以通过POST进行纠正)。
#12
-1
If you really don't want to use multiple forms (as Jason sugests), then use buttons and onclick handlers.
如果您真的不想使用多个表单(如Jason sugests),则使用按钮和onclick处理程序。
<form id='form' name='form' action='path/to/add/edit/blog' method='post'>
<textarea name='message' id='message'>Blog message here</textarea>
<input type='submit' id='save' value='Save'>
</form>
<button id='delete'>Delete</button>
<button id='cancel'>Cancel</button>
And then in javascript (I use jQuery here for easyness) (even though it is pretty overkill for adding some onclick handlers)
然后在javascript中(我在这里使用jQuery来简化)(尽管添加onclick处理程序有点过分)
$('#delete').click( function() {
document.location = 'path/to/delete/post/id';
});
$('#cancel').click( function() {
document.location = '/home/index';
});
Also I know, this will make half the page not work without javascript.
我也知道,这将使页面的一半不能没有javascript。
#13
-1
In response to a question posted by Yar in a comment to his own answer, I present some JavaScript which will resize an iframe. For the case of a form button, it is safe to assume the iframe will be on the same domain. This is the code I use. You will have to alter the maths/constants for your own site:
在回答Yar对自己的回答发表评论时,我提出了一些可以调整iframe大小的JavaScript。对于表单按钮,可以安全地假设iframe将位于相同的域中。这是我使用的代码。你必须改变你自己网站的数学/常数:
function resizeIFrame(frame)
{
try {
innerDoc = ('contentDocument' in frame) ? frame.contentDocument : frame.contentWindow.document;
if('style' in frame) {
frame.style.width = Math.min(755, Math.ceil(innerDoc.body.scrollWidth)) + 'px';
frame.style.height = Math.ceil(innerDoc.body.scrollHeight) + 'px';
} else {
frame.width = Math.ceil(innerDoc.body.scrollWidth);
frame.height = Math.ceil(innerDoc.body.scrollHeight);
}
} catch(err) {
window.status = err.message;
}
}
Then call it like this:
然后这样称呼它:
<iframe ... frameborder="0" onload="if(window.parent && window.parent.resizeIFrame){window.parent.resizeIFrame(this);}"></iframe>
#14
-1
I just came up with a nice way of doing it with jquery.
我刚刚想出了一种使用jquery的好方法。
<form name="mainform">
<div id="placeholder">
<div>
</form>
<form id="nested_form" style="position:absolute">
</form>
<script>
$(document).ready(function(){
pos = $('#placeholder').position();
$('#nested_form')
.css('left', pos.left.toFixed(0)+'px')
.css('top', pos.top.toFixed(0)+'px');
});
</script>
#15
-1
I went around the issue by including a checkbox depending on what form the person wanted to do. Then used 1 button to submit the whole form.
我通过包括一个复选框来解决这个问题,这取决于这个人想要做什么。然后使用1按钮提交整个表单。
#16
-2
Alternatively you could assign the form actiob on the fly...might not be the best solution, but sure does relieve the server-side logic...
或者,您可以动态地分配表单actiob……可能不是最好的解决方案,但肯定会减轻服务器端逻辑……
<form name="frm" method="post">
<input type="submit" value="One" onclick="javascript:this.form.action='1.htm'" />
<input type="submit" value="Two" onclick="javascript:this.form.action='2.htm'" />
</form>