我知道XHTML不支持嵌套的表单标记,我已经在Stack Overflow上阅读了关于这个主题的其他答案,但我仍然没有找到一个优雅的解决方案。

有些人说你不需要它,他们想不出有什么场景会需要它。就我个人而言,我想不出任何一种情况下我不需要它。

让我们看一个非常简单的例子:

你正在制作一个博客应用程序,你有一个带有一些字段的表单用于创建新帖子,还有一个带有“操作”的工具栏,如“保存”、“删除”、“取消”。

<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>

我们的目标是以一种不需要JavaScript的方式编写表单,只需要普通的HTML表单和提交按钮。

由于动作URL是在Form标签中定义的,而不是在每个单独的提交按钮中,所以我们唯一的选择是发布到一个通用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”这样的副作用操作永远不应该是GET请求。

所以我的问题是(特别是对那些说他们不需要表单嵌套的人)你会做什么?有什么优雅的解决方案,我错过或底线真的是“要么需要JavaScript或提交一切”?


当前回答

对嵌套表单使用iframe。如果他们需要共享场地,那么……它并不是真正的嵌套。

其他回答

我通过添加一个复选框来绕过这个问题,这取决于人们想要什么样的形式。 然后使用1个按钮提交整个表单。

如果你真的不想使用多个表单(就像Jason建议的那样),那么就使用按钮和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>

然后在javascript中(为了简单起见,我在这里使用jQuery)(尽管添加一些onclick处理程序有点多余)

$('#delete').click( function() {
   document.location = 'path/to/delete/post/id'; 
});
$('#cancel').click( function() {
   document.location = '/home/index';
});

我也知道,如果没有javascript,这将使一半的页面无法工作。

这是一个老话题了,但这个可能对某些人有用:

正如上面有人提到的,你可以使用虚拟形式。 前段时间我不得不克服这个问题。起初,我完全忘记了这个HTML限制,只是添加了嵌套表单。结果很有趣——我从嵌套中丢失了我的第一个表单。然后,它被证明是一种“技巧”,只是在实际的嵌套表单之前添加一个虚拟表单(将从浏览器中删除)。

在我的例子中,它看起来是这样的:

<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>

工作良好的Chrome, Firefox和Safari。IE高达9(不确定10)和Opera不检测参数在主要形式。不管输入是什么,$_REQUEST全局变量都是空的。内在形式似乎在任何地方都很有效。

还没有测试这里描述的另一个建议-围绕嵌套表单的fieldset。

编辑:框架不起作用! 我只是在其他表单之后添加了Main表单(不再嵌套表单),并使用jQuery的“克隆”来复制按钮单击表单中的输入。添加.hide()到每个克隆的输入以保持布局不变,现在它就像一个魅力。

我刚刚想出了一个很好的方法来做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>

对嵌套表单使用iframe。如果他们需要共享场地,那么……它并不是真正的嵌套。