266

I'm including some forms inside a HTML table to add new rows and update current rows. The problem that I'm getting is that when I inspect the forms in my dev tools, I see that the form elements are closed immediately after opening (inputs, etc are not included within the form).

As such, submitting a form fails to include the fields.

The table row and inputs are as follows:

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

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

Any help would be great, thank you.

Alex
  • 7,793
  • 9
  • 41
  • 54

3 Answers3

407

A form is not allowed to be a child element of a table, tbody or tr. Attempting to put one there will tend to cause the browser to move the form to it appears after the table (while leaving its contents — table rows, table cells, inputs, etc — behind).

You can have an entire table inside a form. You can have a form inside a table cell. You cannot have part of a table inside a form.

Use one form around the entire table. Then either use the clicked submit button to determine which row to process (to be quick) or process every row (allowing bulk updates).

HTML 5 introduces the form attribute. This allows you to provide one form per row outside the table and then associate all the form control in a given row with one of those forms using its id.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
  • 2
    Take care using one form for the entire table, all fields will be send to server, even if they are empty. It could be a huge amount of data !!! Please for mass/public usage, prefer to use a dialog (form not in table) opened from a button in that row. – Loenix Feb 13 '16 at 10:41
  • 1
    @Loenix: It is very unlikely that you'll put enough data in the table for it to be a significant burden on people's bandwidth (at least when compared to the size of a typical webpage). Requiring users to load another page between choosing to edit a row and being able to make their changes, OTOH, would be an annoying extra interaction that they would have to perform. – Quentin Feb 13 '16 at 10:55
  • I was not talking about opening another page but to use a dialog/modal. e.g http://getbootstrap.com/javascript/#modals-examples This allow you to use a more beautiful form, to get more inputs in an optimized way. When you display 100+ rows with 10 inputs each... it's getting much – Loenix Feb 13 '16 at 15:55
  • It's still an extra interaction for the user (and negates the possibility of doing batch updates). – Quentin Feb 13 '16 at 21:53
  • This is not really an extra interaction... You still need an edit button and a save button for both solution. It negates the possibility of doing batch updates but make your choice for quite substantial forms (> 3 fields), the inline form will be unusable and the user will not do batch updates. I don't tell you that you have to do this way but just dont forget to consider this problem. ;-) – Loenix Feb 14 '16 at 22:58
  • 1
    You don't need an edit button for the solution proposed in the original question. – Quentin Feb 15 '16 at 07:50
  • 1
    Why did the prohibited `
    ` inside of `` in the standards?
    – 1234ru Aug 11 '17 at 08:44
  • @1234ru — I wouldn't want to speculate on the reasons that people made a design decision two decades ago. – Quentin Aug 11 '17 at 08:51
  • 4
    @Qentin fair enough. It's a pity this still stands after two decades with no obvious reason. – 1234ru Aug 12 '17 at 11:39
  • @1234ru — It still stands because backwards compatibility is important – Quentin Mar 29 '18 at 08:25
  • 1
    @GeneCode — No code sample could explain things as clearly as the first two sentences of the middle paragraph. – Quentin Mar 29 '18 at 08:26
212

Use the "form" attribute, if you want to save your markup:

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

(*Form fields outside of the < form > tag)

030
  • 8,013
  • 8
  • 63
  • 100
Vladimir
  • 3,991
  • 1
  • 24
  • 28
  • 64
    Note, this solution is only valid with HTML5. – threenplusone Feb 14 '14 at 04:18
  • 18
    moreover, it won't work in internet explorer [more info here](http://caniuse.com/#feat=form-attribute) – Souhaieb Besbes Aug 27 '15 at 09:50
  • Is there any plan to make it IE compatible, do you know @SouhaiebBesbes? I can't get my form working any other way. – Zoinks10 Apr 05 '16 at 00:53
  • 1
    The status of form attribute is 'under consideration' which means you have to be very patient https://developer.microsoft.com/en-us/microsoft-edge/platform/status/formattribute meanwhile you can try this polyfill and see if it works for you http://stackoverflow.com/a/26696165/648484 – Souhaieb Besbes Apr 05 '16 at 08:24
  • 1
    Seems "in development" now, and ok to use – user1156544 Jun 19 '17 at 13:47
  • 1
    @user1156544 It's supported in Edge now, but not IE. If you need to support IE at all, you're out of luck with this solution. My plan is to use two tables for two form elements (I can't believe I have to do this). Thanks Microsoft! – Pluto May 31 '19 at 18:47
  • @Pluto This is the straw that's going to break the camel's back of IE 11 support at our company. It's six years old now. It's time for it to die. – Jacob Stamm Aug 07 '19 at 18:11
47

If you want a "editable grid" i.e. a table like structure that allows you to make any of the rows a form, use CSS that mimics the TABLE tag's layout: display:table, display:table-row, and display:table-cell.

There is no need to wrap your whole table in a form and no need to create a separate form and table for each apparent row of your table.

Try this instead:

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

The problem with wrapping the whole TABLE in a FORM is that any and all form elements will be sent on submit (maybe that is desired but probably not). This method allows you to define a form for each "row" and send only that row of data on submit.

The problem with wrapping a FORM tag around a TR tag (or TR around a FORM) is that it's invalid HTML. The FORM will still allow submit as usual but at this point the DOM is broken. Note: Try getting the child elements of your FORM or TR with JavaScript, it can lead to unexpected results.

Note that IE7 doesn't support these CSS table styles and IE8 will need a doctype declaration to get it into "standards" mode: (try this one or something equivalent)

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

Any other browser that supports display:table, display:table-row and display:table-cell should display your css data table the same as it would if you were using the TABLE, TR and TD tags. Most of them do.

Note that you can also mimic THEAD, TBODY, TFOOT by wrapping your row groups in another DIV with display: table-header-group, table-row-group and table-footer-group respectively.

NOTE: The only thing you cannot do with this method is colspan.

Check out this illustration: http://jsfiddle.net/ZRQPP/

Matthew
  • 7,255
  • 10
  • 33
  • 63
  • 4
    +1 for mentioning this does not enable colspan... which I must have missed the first reading it through ;-) – Johannes Rudolph Mar 19 '17 at 20:29
  • 1
    That should be the green checked answer (even if don't use really table tag) – Alessio May 03 '19 at 13:22
  • " Note: Try getting the child elements of your FORM or TR with JavaScript, it can lead to unexpected results." That´s exactly how I learned it despite this being a very old post. Who pays the "define standards" guys? I wan´t a word with them – alvaroc Apr 24 '21 at 01:56