0

I am attempting to use a structure like the following (of course this is a "bare-bones" example, the actual table is generated by PHP and consists of multiple files, inputs, and many more <td>'s):

<table>
    <!-- loop($iterator=0; $iterator < num_of_rows; $iterator++) -->
    <tr id='"row-'.$iterator.'"'>
        <form action="uploadHandler.php" method="post" enctype="multipart/form-data" id='"form-'.$iterator.'"' class="form-uploader">
            <td><input type="file" class="main-img" name="main-img"/></td>
            <td><input type="text" name="main-img-title" /></td>
            <td><input type="submit" /></td>
        </form>
    </tr>
    <!-- end loop -->
</table>

However, I have read that anything other than a <td> within a <tr> and anything other than a <tr>,<caption>,<thead>/<tbody>/<tfoot> within a <table> is not valid HTML. Also, we added Data Tables (https://datatables.net/) to the above structure and due to the Data Tables removing/rebuilding table elements anything other than the table elements gets wiped out anyway.

Solutions?

  1. One thought was to move the <form> element to avoid this complication. I was unsuccessful here because for functionality reasons the form must encapsulate multiple <td>'s, but cannot encapsulate multiple <tr>'s. I cannot wrap <tr>'s because it is invalid HTML, as is the form inside the <tr>. The <form> cannot be inside a <td> because it must encompass multiple <td>'s and as soon as the <td> is closed, the <form> is subsequently closed.

  2. With JS: I thought about having one static hidden form on the page. Upon submission of the form in the Data Table, intercede the form's standard submission and populate the hidden form with the appropriate <input> elements and use AJAX (and a FormData object) to submit that hidden form. That thought looks something like this:

    $(document).ready(function() {
        $(".form-uploader").submit(function(e) {
            e.preventDefault();
            var identifier = $(this).attr("id");
            //idVal represents the $iterator (in table above)
            //idVal is used to retrieve the appropriate row/inputs from the table of rows above
            var idVal = identifier.substring(identifier.lastIndexOf("-")+1, identifier.length);
            var mainImage = $("#row-"+idVal+" .main-img");
            if(mainImage) {
                alert("mainImage found: " + JSON.stringify(mainImage));
                //move inputs from Data Table row to static-hidden form
                //use FormData obj to post the static-hidden form
            }
            else {
                alert("id: "+idVal+" No main image found");
            }
            //return true when testing is complete
            return false;
        }
    }
    

    Now somehow this finds the appropriate number of inputs (as I have tested with multiple inputs), BUT the Javascript object mainImage looks like this mainImage found: {"0":{},"length":1,...}! Where I expected an <input> object at index 0, I got { }...empty!

  3. Finally, I am hoping some jQuery Guru out there can point me in the right direction for how to appropriately retrieve and move the desired <input type="file"> OR someone who can help solve the underlying problem in the structure of my solution and it's compatibility with the HTML table/Data Tables!

Here and many others are similar questions, but the answers suggest using CSS to stylize tables. These are not preferred as the <table> is required for the Data Tables and comes with desired styling (no sense in reinventing the wheel). I also seen form attribute for the inputs but this does not work in IE. Here suggested encapsulating the entire table with a form, but offered no help as to how to differentiate between rows.

I appreciate any and all help with my first Stack Question and I thank you for your time and consideration!

Community
  • 1
  • 1
Isaiah
  • 484
  • 5
  • 16

1 Answers1

0

This would explain why I could not simply grab the <input type="file"> and move it to another form in JS. Basically, the restrictions of Javascript being client-side prevents most of the file data from being accessible. Safety first kids!

Ultimately, I believe that the sound solution to "rows of input(s) within a table" starts with the form encapsulating the entire table. From there you must distinguish between the data accordingly. This likely varies depending on your server-side language, mine was PHP so I used the following methodology:

  1. Utilize submit buttons with the same name attribute but unique value attributes within them. In PHP using something like echo $_POST['submit-button'] will only return the value of the submit button pressed even if there are others with the same name.

  2. With this I was able to utilize a unique identifier for each <input> in each <tr> that I could use to group all inputs by row.

  3. To finish, I appended this unique identifier to my name attributes across all inputs in the form and when handling the post.

A short example:

uploadHandler.php

<?php
    if(isset($_POST['upload-button'])) {
        $identifier = $_POST['upload-button'];//this is the unique identifier for this row (see table below)
        //(All inputs would be contained in the all-encapsulating form, we only want ones from the row!)
        //Use $identifier to distinguish between <input>'s!
        $main_img = $_FILES['main-img'.$identifier];
        $main_img_title = $_POST['main-img-title'.$identifier];
    }
?>

formPage.php

<form method="post" action="uploadHandler.php" enctype="multipart/form-data">
    <table>
    <!-- loop($iterator=0; $iterator < num_of_rows; $iterator++) -->
        <tr id='"row-'.$iterator.'"'>
            <td><input type="file" class="main-img" name="main-img'.$iterator.'" /></td>
            <td><input type="text" name="main-img-title'.$iterator.'" /></td>
            <td><input type="submit" name="upload-button" value="'.$iterator.'" /></td>
        </tr>
    <!-- end loop -->
    </table>
</form>
Community
  • 1
  • 1
Isaiah
  • 484
  • 5
  • 16