表格内的表单

Form inside a table

提问人:Alex 提问时间:5/12/2011 最后编辑:Alex 更新时间:5/21/2023 访问量:508069

问:

我在 HTML 表格中包含一些表单以添加新行和更新当前行。我遇到的问题是,当我在开发工具中检查表单时,我看到表单元素在打开后立即关闭(输入等不包含在表单中)。

因此,提交表单无法包含字段。

表行和输入如下:

<tr>
    <form method="post" action="">
        <td>
            <input type="text" name="job_num">
        </td>

        <td>
            <input type="text" name="desc">
        </td>
    </form>
</tr>

任何帮助都会很棒,谢谢。

Firebug HTML 表格 表单

评论

12赞 Derek 朕會功夫 7/22/2011
<form>不能放进去。<tr>
1赞 Derek 朕會功夫 7/22/2011
而且您忘记关闭 .<tr>
1赞 Matthew 3/24/2013
将 display:table-row 用于表单,并完全放弃 table 标记。在这里查看我的答案:stackoverflow.com/a/15600151/1038812
0赞 Sandburg 8/27/2019
它不能,但它有效......

答:

468赞 Quentin 5/12/2011 #1

表单不允许是 或 的子元素。尝试将表单放在那里往往会导致浏览器将表单移动到表格之后(同时将其内容(表格行、表格单元格、输入等)留在后面)。tabletbodytr

您可以在窗体中拥有整个表。您可以在表格单元格中创建一个表单。表单中不能包含表格的一部分。

在整个表格中使用一个表单。然后,使用单击的提交按钮确定要处理的行(以便快速)或处理每一行(允许批量更新)。

HTML 5 引入了 form 属性。这允许您在表外每行提供一个窗体,然后使用给定行中的所有窗体控件与其 .id

评论

4赞 Loenix 2/13/2016
请注意对整个表使用一个表单,所有字段都将发送到服务器,即使它们是空的。这可能是大量的数据!!对于大众/公众使用,请更喜欢使用从该行中的按钮打开的对话框(不在表格中的表单)。
2赞 Quentin 2/13/2016
@Loenix:你不太可能在表格中放置足够的数据,以至于它对人们的带宽造成重大负担(至少与典型网页的大小相比)。要求用户在选择编辑一行和能够进行更改之间加载另一个页面,OTOH 将是他们必须执行的烦人的额外交互。
1赞 Quentin 2/14/2016
对于用户来说,这仍然是一个额外的交互(并且否定了进行批量更新的可能性)。
1赞 Quentin 2/15/2016
对于原始问题中提出的解决方案,您不需要编辑按钮。
5赞 1234ru 8/12/2017
@Qentin很公平。遗憾的是,二十年后,这仍然屹立不倒,没有明显的原因。
251赞 Vladimir 2/7/2014 #2

如果要保存标记,请使用“form”属性

<form method="GET" id="my_form"></form>

<table>
    <tr>
        <td>
            <input type="text" name="company" form="my_form" />
            <button type="button" form="my_form">ok</button>
        </td>
    </tr>
</table>

(*<表单>标签之外的表单字段)

评论

68赞 threenplusone 2/14/2014
请注意,此解决方案仅对 HTML5 有效。
18赞 Souhaieb Besbes 8/27/2015
此外,它在 Internet Explorer 中不起作用 更多信息在这里
1赞 Souhaieb Besbes 4/5/2016
表单属性的状态是“正在考虑中”,这意味着你必须非常耐心地 developer.microsoft.com/en-us/microsoft-edge/platform/status/......同时,你可以试试这个polyfill,看看它是否适合你 stackoverflow.com/a/26696165/648484
1赞 user1156544 6/19/2017
现在似乎“正在开发中”,可以使用
1赞 Pluto 6/1/2019
@user1156544 Edge 现在支持它,但 IE 不支持它。如果你需要支持IE,那么这个解决方案就不走运了。我的计划是将两个表用于两个表单元素(我不敢相信我必须这样做)。谢谢 Microsoft!
60赞 Matthew 1/27/2016 #3

如果你想要一个“可编辑的网格”,即一个类似表格的结构,允许你使任何一行成为表单,请使用模仿TABLE标签布局的CSS:、和。display:tabledisplay:table-rowdisplay:table-cell

无需将整个表格包装在一个表单中,也无需为表格的每个明显行创建单独的表单和表格。

请尝试以下操作:

<style>
DIV.table 
{
    display:table;
}
FORM.tr, DIV.tr
{
    display:table-row;
}
SPAN.td
{
    display:table-cell;
}
</style>
...
<div class="table">
    <form class="tr" method="post" action="blah.html">
        <span class="td"><input type="text"/></span>
        <span class="td"><input type="text"/></span>
    </form>
    <div class="tr">
        <span class="td">(cell data)</span>
        <span class="td">(cell data)</span>
    </div>
    ...
</div>

将整个 TABLE 包装在 FORM 中的问题在于,任何和所有表单元素都将在提交时发送(也许这是需要的,但可能不是)。此方法允许您为每个“行”定义一个表单,并在提交时仅发送该行数据。

将 FORM 标签包裹在 TR 标签(或 TR 包裹在 FORM 周围)的问题在于它是无效的 HTML。FORM 仍将允许像往常一样提交,但此时 DOM 已损坏。注意:尝试使用 JavaScript 获取 FORM 或 TR 的子元素,这可能会导致意外结果。

请注意,IE7 不支持这些 CSS 表格样式,IE8 需要一个 doctype 声明才能使其进入“标准”模式:(试试这个或等效的东西)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

任何其他支持 display:table、display:table-row 和 display:table-cell 的浏览器都应该像使用 TABLE、TR 和 TD 标签一样显示 css 数据表。他们中的大多数人都这样做。

请注意,您还可以模拟 THEAD、TBODY、TFOOT,方法是将行组分别用 和 包装在另一个 DIV 中。display: table-header-grouptable-row-grouptable-footer-group

注意:使用此方法唯一不能做的是 colspan。

请看这个插图: http://jsfiddle.net/ZRQPP/

评论

6赞 Johannes Rudolph 3/20/2017
+1 提到这不会启用 colspan...我一定错过了第一次通读它;-)
2赞 Alessio 5/3/2019
这应该是绿色检查的答案(即使不使用真正的表标签)
0赞 alvaroc 4/24/2021
“注意:尝试使用 JavaScript 获取 FORM 或 TR 的子元素,可能会导致意外结果。”这正是我学习它的方式,尽管这是一个非常古老的帖子。谁付钱给“定义标准”的人?我不想和他们说一句话
0赞 cani 5/21/2023 #4

尽管正如昆汀所提到的,不允许将表格放在表格中。我们可以使用 Web 组件中使用的插槽来解决此限制。

首先,我们需要在 HTML 文件中创建一个表格模板:

<template id="my-table">
  <table>
    <tr>
      <td>first column</td>
      <td>second column <slot name="my-form"></slot></td>
      <td>third column</td>
    </tr>
  </table>
</template>

slot 元素是一个插入点,具有属性的元素将呈现在插入点内部。slot="my-form"

然后我们在 JS 中定义一个自定义组件:

customElements.define(
  "my-table",
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById("my-table");
      let templateContent = template.content;

      const shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(templateContent.cloneNode(true));
    }
  }
);

为了使用插槽,我们需要使用影子 DOM,这就是为什么我们将影子根附加到自定义元素,它包含模板的内容。

现在我们可以回到 HTML 文件并使用自定义表组件

<my-table>
  <form action="" slot="my-form">
    <input type="text" name="name" id="" />
    <button>Submit</button>
  </form>
</my-table>

上面的表单元素引用了命名的插槽,因此它将被放置在其中。"my-form"

此解决方法有效,因为表单元素未显式放置在表中。窗体只是在 slot 元素中呈现,如下所示:

DOM structure