0

I recently ran into a problem I wasn't quite sure how to solve. Sharing it here in case it helps someone else.

Use Case: User enters a string in a search box on a PHP page. On submit, the page queries the database and then posts results to a table on the same page. User then selects a single record with a radio button and needs to post only that record to a different PHP page. The second page does not have access to the database.

I took the actual page and created a sample page for clarity and testing, since the original had about 15 table columns.

<div class="container">
    <div class="row" style="margin-top: 1rem;">
        <div class="col-sm">                         
            <form action="" method="post">                    
                <table class="fit" id="entry">
                    <tr>
                        <td class="fit"><label for="start">Planet (try <strong>Caprica</strong> or <strong>Picon</strong>): </label></td>                            
                    </tr>
                    <tr>                            
                        <td class="fit"><input type="test" id="planet" name="planet" required autofocus /></td>
                    </tr>                        
                </table>                        
                <input class="btn btn-primary" type="submit" value="Get Characters" />
            </form>
        </div>
    </div>
</div>  

<div class="container" style="margin-top: 2rem;">
    <div class="row">
        <div class="col-sm">               
            <?php
            require_once('./resources/pdo.php');

            if ( isset($_POST['planet']) ) {

                $planet = strtolower($_POST['planet']);      
                $pdo = new myPDO('phppostpost');

                try {
                    $stmt = $pdo->prepare('CALL devCharacters(?)');
                    $stmt->bindParam(1, $planet, PDO::PARAM_STR);                    
                    $stmt->execute();                        
                    $stmt->setFetchMode(PDO::FETCH_ASSOC);
                } catch (PDOException $e) {
                    die("Error occurred: " . $e->getMessage());
                }
                ?>

                <div class="table-responsive">

                    <table class="table table-striped table-hover">
                        <thead class="thead-light">
                            <tr>
                                <th class="fit">Select</th>                                           
                                <th class="fit" scope="col">Customer First</th>
                                <th class="fit" scope="col">Customer Last</th>
                                <th class="fit" scope="col">Planet</th>
                            </tr>
                        </thead>
                        <tbody>
                        <?php while ($r = $stmt->fetch()): ?>                             
                            <tr>                                    
                                <?php echo "<td class='fit'><input type='radio' id='cust-" . $r['customer_id'] ."' name='cust-id' value='". $r['customer_id'] . "' </td>"; ?>
                                <?php echo "<td class='fit'>" . $r['first_name'] . "</td>"; ?>
                                <?php echo "<td class='fit'>" . $r['last_name'] . "</td>"; ?>
                                <?php echo "<td class='fit'>" . $r['origin_planet'] . "</td>"; ?>
                            </tr>
                        <?php endwhile; ?>
                        </tbody>
                    </table>
                </div>
                <input class="btn btn-primary" onclick="getSelectedRowData();" type="submit" value="Send" />
            <?php } ?>
        </div>
    </div>
</div> 

As a relatively new developer, I couldn't figure out how to (1) grab just the selected row and (2) post data on submit from just that row, rather than from the the original search form.

After much Googling, as well as a kick in the pants from a Stack Overflow user who reminded me I needed to actually research for more than 20 minutes (thank you!), I was able to solve it.

I'll post the answer below for anyone else who runs into a similar problem.

paulmiller3000
  • 436
  • 8
  • 24

1 Answers1

0

To solve this, I used JavaScript to grab the selected row. In order to efficiently grab the correct record, I updated each TD element to have a unique, dynamically-generated ID:

<?php echo "<td class='fit' id='fname-" . $r['customer_id'] ."'>" . $r['first_name'] . "</td>"; ?>
<?php echo "<td class='fit' id='lname-" . $r['customer_id'] ."'>" . $r['last_name'] . "</td>"; ?>
<?php echo "<td class='fit' id='planet-" . $r['customer_id'] ."'>" . $r['origin_planet'] . "</td>"; ?>

I also gave the table body an ID so I could grab it quickly without grabbing a parent, then children, etc.:

<tbody id="results-body">

Finally, here's the JavaScript.

function getSelectedRowData() {             
    const tableRowArray = Array.from([document.getElementById('results-body')][0].rows);

    let custFirst;
    let custLast;
    let custPlanet;

    tableRowArray.forEach((tableRow, i) => {                
        cellButton = tableRow.getElementsByTagName('input');
        if (cellButton[0].checked == true ) {                                                          
            const rowID = cellButton[0].id.split('-').pop();
            custFirst = document.getElementById('fname-' + rowID).innerHTML;
            custLast = document.getElementById('lname-' + rowID).innerHTML;
            custPlanet = document.getElementById('planet-' + rowID).innerHTML;
        }
    });

    /* Build a hidden form solution to prep for post.
       Source: https://stackoverflow.com/questions/26133808/javascript-post-to-php-page */
    let hiddenForm = document.createElement('form');

    hiddenForm.setAttribute('method', 'post');
    hiddenForm.setAttribute('action', 'newpage.php');
    hiddenForm.setAttribute('target', 'view');

    const fieldCustFirst = document.createElement('input');
    const fieldCustLast = document.createElement('input');
    const fieldCustPlanet = document.createElement('input');

    fieldCustFirst.setAttribute('type', 'hidden');
    fieldCustFirst.setAttribute('name', 'custFirst');
    fieldCustFirst.setAttribute('value', custFirst);

    fieldCustLast.setAttribute('type', 'hidden');
    fieldCustLast.setAttribute('name', 'custLast');
    fieldCustLast.setAttribute('value', custLast);

    fieldCustPlanet.setAttribute('type', 'hidden');
    fieldCustPlanet.setAttribute('name', 'custPlanet');
    fieldCustPlanet.setAttribute('value', custPlanet);

    hiddenForm.appendChild(fieldCustFirst);
    hiddenForm.appendChild(fieldCustLast);
    hiddenForm.appendChild(fieldCustPlanet);

    document.body.appendChild(hiddenForm);

    // Post
    window.open('', 'view');
    hiddenForm.submit();
} 

This worked for me, but I'm sure there's a better way to do this. Hopefully this (1) helps someone else and (2) a better solution is posted!

Here's a working demo: https://postfrompost.paulmiller3000.com/

Full source here: https://github.com/paulmiller3000/post-selected-from-post

paulmiller3000
  • 436
  • 8
  • 24