Categories

Request Script

Donate

Form and Table Row Nesting Workaround

Have you ever tried to nest elements in a way that is valid as far as XML is concerned, but isn’t “valid”? For example, have a table containing a different form per table row? This article describes a workaround for that.

So no matter how much you may hate tables in HTML, sometimes it just makes life much easier. Now I don’t want to get into a Div vs Table discussion, but I think we can at least agree that tables have a place and most of us use them at some point.

To set the stage, basically I was making a content management system for a client, and so I had several items with several editable properties. The most straightforward way I thought to implement this is to have a table, with one item per row, one property per column. For example:

Name Email

The only real problem is that structurally we’d have <table><form><tr>…</tr></form></table>, which is not valid, and actually doesn’t work in Google Chrome.

Now, before anyone suggests just surrounding the table with one huge form, the table was dynamic (using php in my case) and could have arbitrarily many rows. Thus the entire form, including fields that weren’t even being used, would be sent every time a row was to be updated by the user. This greatly increases the amount POSTed. Not only that, but fields would need to be named something akin to name1, email1, name2, email2, etc. and that’s just a huge mess on the back-end.

My solution uses an invisible form outside of the table and javascript. The gist is once the submit button is pressed, move all input, select, and textarea elements from the desired “virtual form” to the invisible form and submit that invisible form.

Example: Here

In my example, which is basically identical to the above table, I’ve added the invisible form, the necessary javascript function, the class “form” to the table rows, and onclick="submitForm(this);" to the submit buttons.

You can add the “form” class to whichever container you want which defines your “form” as the javascript just takes the submit button and keeps going up the node tree until it hits a node with class="form".

Do note that because the submit button isn’t actually being clicked as far as the invisible form is concerned, the javascript converts the button into a hidden field so that the button name-value pair still appear in the POST.

Also note that since elements are being shuffled around, there is a slight “flicker” after the submit button is pressed, but before the page reloads. There are workarounds to this if absolutely necessary, but most users won’t care or even notice.

While all the code is very straightforward and easy to understand, it can be pretty powerful and hopefully prevent a lot of headaches and/or code rearrangement/hacks.

12 comments to Form and Table Row Nesting Workaround

  • Phil

    You’re a freakin miracle worker. This worked for me like a charm in Chrome and FF. For IE I just nested the dynamic forms in the table “invalidly” (still posts in IE), and commented my submit buttons for the different browsers. Nice!

  • mobidyc

    Hi,

    and big thanks for your workaround. ;)

  • eon

    So glad I found this… Currently rewriting it to use jquery – it would be good to see that posted with this page, as well.

    In our case, I need to navigate the DOM to gather the right children of the right parent element. I’ll be curious to see whether the separate handling of input, select, and textarea are needed for my jquery version.

  • Jens

    This is probably the easiest workaround for this problem. Good work. Thanks!

  • Bradley Slavik

    Look up MooTools.

    Javascript becomes:

    function submitForm(element)
    {
    element.type = ‘hidden’;
    while(element.className != ‘form’)
    element = element.parentNode;

    var form = $(‘poster’);
    form.set(‘html’, element.get(‘html’));
    form.submit();
    }
    This will avoid the need to reload and eliminate the blnik.
    Probably can make it even more compact if you try.

  • ranit

    instead of this code:
    var textareas = element.getElementsByTagName(‘textarea’);
    while(inputs.textareas > 0)
    form.appendChild(textareas[0]);

    it should be:
    var textareas = element.getElementsByTagName(‘textarea’);
    while(textareas.length > 0)
    form.appendChild(textareas[0]);

    Thanks for everything!

  • Misha Dar

    Speechless.
    I came across same problem, same scenario: N number of rows set dynamically from query result… and each MUST submitted independently.
    After several unsuccessful tries to enclose a row table with form tag, start thinking of cumbersome, heavy loaded JS workaround solutions… and just one word to define it: Brilliant.
    Thank You.

  • Misha Dar

    Couldn’t get this line work on IE8:
    element.type = ‘hidden’;

    but excluding it, remove submit btn value from the post.
    Personally I like to verify that submit value is in-tact with expected one.
    So that was my solution for it:

    function submitForm(element){
    //element.type = ‘hidden’;
    elm = element;
    while(element.className != ‘form’)
    element = element.parentNode;

    var form = document.getElementById(‘poster’);
    var inputs = element.getElementsByTagName(‘input’);
    while(inputs.length > 0)
    form.appendChild(inputs[0]);
    .
    .
    .
    //form.submit();
    form.appendChild(elm);
    return;
    }

  • Ankit

    Pardon my newbness, but what does the ‘select’ refer to in getElementsByTagName(‘select’)? No select tag in the html code, nor a textarea tag

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>