你可以嵌套HTML表单吗?

557

可以像这样嵌套HTML表单吗?

<form name="mainForm">
  <form name="subForm">
  </form>
</form>

这样两种形式都能工作吗?我的朋友在这方面遇到了问题,subForm的一部分可以工作,而另一部分却不能。

1
他正在设置一个购物车,其中更新数量在跟踪总计的表单内部。个人而言,我不会这样做,但他遇到了问题,无法使其正常工作。 - Levi
1
似乎他最好使用JavaScript从一个表单复制值到另一个表单,而不是尝试嵌套它们。我认为嵌套不会起作用。 - Ben
你甚至会在同一浏览器的不同版本中遇到问题,使其无法正常工作。因此,请避免使用它。 - MP.
18
为了回答评论,嵌套表单可能是必要的以避免使用JavaScript。我看到这个问题是因为我想为子表单的“重置”按钮嵌套表单,这不需要启用JavaScript。 - vol7ron
是的,我和你一样遇到了这个问题。我使用了ajax提交表单来解决这个问题。 - Khanh Pham
21个回答

541
总之,不行。您可以在页面中有几个表单,但它们不应嵌套。

HTML5工作草案中:

4.10.3 form元素

内容模型:

流内容,但没有表单元素的后代。


164
我同意这个答案,但我有另一个问题:为什么HTML不允许嵌套表单?在我看来,这是一个限制,我们最好去掉它。使用嵌套表单会更容易进行编程,比如使用上传照片表单和个人资料编辑表单。 - Ryan
38
@Nilzor并不是在问它是否可以完成,他在问为什么不能这样做。我同意,嵌套表单非常有用。因此,如果您有一个带有选项卡的单页应用程序,每个选项卡都是自己的表单(以便可以提交它来保存进度),它们都包含在一个表单中,您可以提交它来保存所有内容。这对我来说很有意义。 - Rob Grant
8
我同意其他人的说法。这种限制似乎是武断和有害的。 - aroth
24
所以我们需要带有嵌套表单的 HTML 5.1 版本。 - Hector
11
嵌套表单的问题在于 HTML 中的表单结构,其中表单中的操作会导致提交事件。关于需要提交什么的问题变得复杂起来。您可能在一个表单中有多个字段,或在一个 div 中有多个表单,但在一个表单中嵌套表单并没有什么意义。如果内容是一起提交的,那么就只是一个表单;如果内容需要分别提交,则实际上是不需要外部表单的独立表单。 - Kyle Baker
显示剩余10条评论

204

HTML5<input>标签的form属性可以解决问题。

来自http://www.w3schools.com/tags/att_input_form.asp

  1. form属性是HTML5中的新属性。
  2. 指定一个<input>元素属于哪个<form>元素。该属性的值必须为同一文档中<form>元素的id属性。

场景:

  • input_Form1_n1
  • input_Form2_n1
  • input_Form1_n2
  • input_Form2_n2

实现:

<form id="Form1" action="Action1.php" method="post"></form>
<form id="Form2" action="Action2.php" method="post"></form>

<input type="text" name="input_Form1_n1" form="Form1" />
<input type="text" name="input_Form2_n1" form="Form2" />
<input type="text" name="input_Form1_n2" form="Form1" />
<input type="text" name="input_Form2_n2" form="Form2" />

<input type="submit" name="button1" value="buttonVal1" form="Form1" />
<input type="submit" name="button2" value="buttonVal2" form="Form2" />

在这里您可以找到浏览器的兼容性。


5
请查看此浏览器支持表:https://caniuse.com/#feat=form-attribute简而言之,它在各种浏览器中都可以使用(Chrome、Firefox、Opera、Edge、Safari、Android 浏览器......),唯独在 IE 中无法使用(包括最新版本 v11)。 - dmikam
2
@cliff-burton,这里有什么区别吗?我只能看到表单外的输入。它仍然需要JS同时提交两个表单,不是吗? - sdlins
5
自上次使用以来已经很长时间了,但我认为提交表单时不需要使用JS。只要<input type="submit"与指定了action<form>相连,那么与该<form>相关联的<input />将会在请求中被使用。 - Cliff Burton

98

可以实现与嵌套表单相同的结果,但不需要将它们嵌套。

HTML5引入了form属性。您可以向表单控件添加form属性,将它们链接到特定的表单元素(通过id)。

https://www.impressivewebs.com/html5-form-attribute/

这样,您可以按照以下方式构造您的HTML:

<form id="main-form" action="/main-action" method="post"></form>
<form id="sub-form"  action="/sub-action"  method="post"></form>

<div class="main-component">
    <input type="text" name="main-property1" form="main-form" />
    <input type="text" name="main-property2" form="main-form" />

    <div class="sub-component">
        <input type="text" name="sub-property1" form="sub-form" />
        <input type="text" name="sub-property2" form="sub-form" />
        <input type="submit" name="sub-save" value="Save" form="sub-form" />
    </div>

    <input type="submit" name="main-save" value="Save" form="main-form" />
</div>

所有现代浏览器都支持form属性。虽然IE不支持该属性,但是据微软确认,IE已经不再是浏览器,而是兼容性工具:https://www.zdnet.com/article/microsoft-security-chief-ie-is-not-a-browser-so-stop-using-it-as-your-default/。是时候摒弃在IE上运行的想法了。

https://caniuse.com/#feat=form-attribute
https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fae-form

来自HTML规范:

该功能允许作者绕过对嵌套表单元素的支持不足。


这里有什么区别吗?我只能看到表单外的输入。它仍然需要JS同时提交两个表单,不是吗? - sdlins
3
不,这个想法是将主组件和子组件样式嵌套在一起,以您想要的外观呈现出来。实际上,两个表单标签将是不可见的。每个提交按钮将触发其相应的表单提交。无需使用JavaScript。 - Creative
1
如果您只想触发一个表单或另一个表单,那么可以。但是,当您需要触发“父”表单及其子表单时,并且不使用js使其像一个表单一样解决问题? - sdlins
2
@sdlins,这不是这个问题的重点。问题是关于两个不同的表单,但它们嵌套在一起。我想知道为什么你想要两个表单,但仍然只有一个提交函数?难道你不能只有一个表单吗?对于像这样奇怪的事情,您确实需要使用JavaScript :P - Creative
是的,你说得对,那不是原帖的问题。我会发表我的问题。谢谢! - sdlins

92
第二个表单将被忽略,例如请参考WebKit中的snippet
bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
    // Only create a new form if we're not already inside one.
    // This is consistent with other browsers' behavior.
    if (!m_currentFormElement) {
        m_currentFormElement = new HTMLFormElement(formTag, m_document);
        result = m_currentFormElement;
        pCloserCreateErrorCheck(t, result);
    }
    return false;
}

44

纯HTML不能让你做到这一点。但是通过JavaScript,您可以实现这一点。 如果您正在使用JavaScript/jQuery,您可以使用类对表单元素进行分类,然后使用serialize()仅序列化您要提交的子集项中的那些表单元素。

<form id="formid">
    <input type="text" class="class1" />
    <input type="text" class="class2">
</form>

然后在你的JavaScript中,你可以这样做来序列化class1元素

$(".class1").serialize();

对于class2,您可以这样做:

$(".class2").serialize();
整个表单
$("#formid").serialize();

或者简单地说

$("#formid").submit();

32
如果您正在使用AngularJS,则ng-app中的任何<form>标签都会在运行时被替换为ngForm指令,这些指令旨在嵌套使用。
在Angular中,表单可以嵌套。这意味着当所有子表单也有效时,外部表单也是有效的。但是,浏览器不允许嵌套<form>元素,因此Angular提供了ngForm指令,其行为与<form>相同,但可以嵌套。这使您可以拥有嵌套表单,在使用动态生成的表单时非常有用,使用ngRepeat指令和Angular验证指令。(来源:source)

1
这就是我正在寻找的答案 :) 是的,嵌套表单是有意义的,因为如果您有多个选项卡,但只想对一个选项卡执行验证,则通过嵌套表单可以实现。 - NeverGiveUp161
WebComponents也是一样吗? - Buddybear

13

如果您正在使用一些服务器端脚本语言来操作提交的数据,那么解决这个问题的另一种方法是像这样声明您的HTML表单:

<form>
<input name="a_name"/>
<input name="a_second_name"/>
<input name="subform[another_name]"/>
<input name="subform[another_second_name]"/>
</form>

如果你打印已发布的数据(这里我将使用PHP),你会得到一个像这样的数组:

//print_r($_POST) will output :
    array(
    'a_name' => 'a_name_value',
    'a_second_name' => 'a_second_name_value',
    'subform' => array(
      'another_name' => 'a_name_value',
      'another_second_name' => 'another_second_name_value',
      ),
    );

那么你可以像这样做:

$my_sub_form_data = $_POST['subform'];
unset($_POST['subform']);

现在您的$_POST仅包含您的“主表单”数据,您的子表单数据存储在另一个变量中,您可以随意操作。

希望这可以帮助您!


12

如 Craig 所说,不。

但是,关于你提到的原因:

使用一个带有输入和“更新”按钮的 <form> ,并在另一个 <form> 中使用复制隐藏输入和“提交订单”按钮可能会更容易些。


我把我的购物车页面做成这样,他走了另一条路,不想改变它。我不确定他的方法是否完全有效。 - Levi

9
你可以在按钮标签内使用formaction =“”属性。
<button type="submit" formaction="/rmDog" method='post' id="rmDog">-</button>

这将作为单独的按钮嵌套在原始表单中。


1
这并没有回答问题,但它帮助我解决了另一个问题,所以我给了个赞。 - codeAndStuff
这是关于编程的内容,以下是翻译:非常有帮助 - 正好符合我今天早上尝试做的事情。这就是为什么我们都喜欢 Stack Overflow。 - codeAndStuff
按钮有一个 formmethod 属性 — https://www.w3schools.com/tags/att_button_formmethod.asp - Inversion

9
注意,不允许嵌套FORM元素! http://www.w3.org/MarkUp/html3/forms.html https://www.w3.org/TR/html4/appendix/changes.html#h-A.3.9(HTML4规范注明从3.2到4没有关于嵌套表单的更改) https://www.w3.org/TR/html4/appendix/changes.html#h-A.1.1.12(HTML4规范注明从4.0到4.1没有关于嵌套表单的更改) https://www.w3.org/TR/html5-diff/(HTML5规范注明从4到5没有关于嵌套表单的更改) https://www.w3.org/TR/html5/forms.html#association-of-controls-and-forms 对于“此功能允许作者绕过不支持嵌套表单元素的限制”,但未注明在哪里进行了说明,我认为他们假设我们应该假定它在HTML3规范中已经被指定 :)

23
我不知道为什么你要在一个已经回答了三年半的问题上发帖,但更麻烦的是链接到了早已不再推荐使用的HTML3。 - Aidiakapi
8
这段话的意思是:这是对问题已被回答多久的参考,我认为这是很有建设性的。另外,我觉得规范中那个毫无 tǎct 的“注意!你不能嵌套 FORM 元素!”很幽默。 - Mark Peterson
1
这是一个问题,因为我必须插入一个API表单,而且由于.NET应用程序(它在所有内容周围包装了一个<form>标记)。你如何解决这个问题? - jelly46
在HTML5规范https://html.spec.whatwg.org/multipage/forms.html#the-form-element中,关于表单元素:“内容模型:流内容,但没有表单元素的后代。” - mems

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接