7

I frequently find myself wanting to make a table of forms -- a bunch of rows, each row being a separate form with its own fields and submit button. For instance, here's an example pet shop application -- imagine this is a checkout screen which gives you the option to update the quantities and attributes of the pets you've selected and save your changes before checking out:

Pet    Quantity Color Variety   Update
snake         4 black rattle    update
puppy         3 pink  dalmatian update

I would love to be able to do this using HTML that looks like this:

<table> 
<thead><tr><th>Pet</th> <th>Quantity</th> <th>Color</th> <th>Variety</th> <th>Update</th></tr></thead>
<tbody>
     <tr>
          <form>
            <td>snake<input type="hidden" name="cartitem" value="55"></td>
            <td><input name="count" value=4/></td>
            <td><select name="color"></select></td>
            <td><select name="variety"></select></td>
            <td><input type="submit"></td>
          </form>
     </tr>
</tbody>
</table>

This is basically a table full of forms, one form per row. Hitting update once allows you to update that specific row (this is not a real example, my real applications really do require independence of rows).

But this is not valid HTML. According to spec, a <form> has to be either completely inside a <td> or completely outside a <table>. This invalid html breaks javascript libraries and is a huge pain to deal with.

I end up making one table to contain column headings, and then making one table per form. But this requires fixed column widths to have the inputs lined up in neat columns, which is sub-par. How do you end up dealing with this problem? Is there an obvious easy solution I'm missing? How to I make a table of forms?

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
Igor Serebryany
  • 3,307
  • 3
  • 29
  • 41
  • Why don't you make it one big form around the table? – Erich Kitzmueller Dec 12 '09 at 13:01
  • 1
    I wouldn't say fixed column widths is sub-par as such. Using `table-layout: fixed` will give you proper fixed column widths (they can be liquid-layout, but they won't change depending on content size, so they'll line up over multiple tables). Fixed table layout also renders sooner. – bobince Dec 12 '09 at 13:22

2 Answers2

15

You can use css to give table layout to other elements.

.table { display: table; } 
.table>* { display: table-row; }
.table>*>* { display: table-cell; }

Then you use the following valid html.

<div class="table"> 
    <form>
        <div>snake<input type="hidden" name="cartitem" value="55"></div>
        <div><input name="count" value=4/></div>
    </form>
</div>
hultqvist
  • 17,451
  • 15
  • 64
  • 101
  • the best answer.. tables being rightly reduced to CSS, FTW! – Gaurav Agarwal May 29 '14 at 09:49
  • I wanted to emphasize the fact that you should _not_ put a `div` to display as the `table-row` around the `div`s that are displaying as a `table-cell`, and that the `form` itself should display as `table-row`. – Ethan Moore Sep 24 '21 at 04:18
6

The trick here is to just use a single form, e.g.

    <form>
      <table>
        <!-- rows... -->
      </table>
      <p><input type="submit" value="Update quantity"></p>
    </form>

Say you have a product snake with id 6. You then name the input for that item's quantity field quantity[6].

I don't know what server side language you are using, but in PHP you can then iterate over the quantites and update based on the ID. You'd get an array like this:

$_POST['quantity'] = array(
    '6' => 4
)
David Snabel-Caunt
  • 57,804
  • 13
  • 114
  • 132
  • 1
    wow - i didn't realize i could do that. this IS helpful, but it makes it hard to know which rows had changes. i guess i could just compare server-side to see if the values are different... – Igor Serebryany Dec 12 '09 at 13:05
  • 1
    @igor, if you find the answer helpful, I think it's considered good practice -as well as good manners- to mark the answer as such by up-voting it. =) and +1 from me. – David Thomas Dec 12 '09 at 13:11
  • 1
    igor: If you have a lot of rows, you could fetch the data with one query and compare. This would save a lot of UPDATEs. That's your call :) – David Snabel-Caunt Dec 12 '09 at 13:23