-1

I have a html table populated by sql select query

<td class="buttonR" onclick="editId(' . $r['code'] . ');">' . $r['code'] . '</td>
<td class="cellL"><input type="text" style="width: 80px" name="category" value="' . $r['category'] . '"></td>
<td class="cellL"><input type="text" style="width: 140px" name="type" value="' . $r['type'] . '"></td>
<td class="cellL"><input type="text" style="width: 300px" name="size" value="' . $r['size'] . '"></td>

Columns display ok:-

code    category    type    size

TB1 stone       green   small
TB2 metal       iron    medium
TB3 wood        pine    large

each code is a button going to a function editId(). category,type and size are text boxes, so can be overwritten. I need that function to run an sql query to update the info from the row text boxes if it is changed in a row and the button pressed.

Unsure on this, this is the update sql for the function but nothing I have tried works.

function editId()
{

$c = "' . $r['code'] . '"

$dbh = dbh_get();    

$sql = "update table 
      set category = '$category',
          type = '$type', 
          size = '$size'
    where code = '$c'";

$stmt = $dbh->prepare($sql);
$stmt->execute($c);

dbh_free($dbh);

}

How can I get the text box values into the function? They're dynamic so if I use document.getElementById('...').value; I assume all id's would be the same

Kilisi
  • 402
  • 11
  • 33

1 Answers1

1

You're trying to call a PHP function (with several issues) from a Javascript event handler. That won't work. You need to use AJAX to send your Javascript action along to a PHP script, and read the response from that.

Let's first think about what you need to do in Javascript:

  1. When the button for a row is clicked, collect all (potentially modified) values for that row, and send it to a PHP script;
  2. After sending the values to PHP, you'll want to prevent the user from making further changes until that PHP script is finished.
  3. When the PHP script is done, allow the user to make further changes again. If the update wasn't successful, tell the user.

Disclaimer: The code examples below are untested. They should help you get on the right track though. If the PHP code does not give you any output, make sure error reporting is enabled so you can see what's going wrong.

Step 1: Preparing your HTML

To be able to collect the values for the row, we need an identifier to select them by. Your <input>s currently don't have one, which will make things more difficult. So let's change that by adding unique id attributes we can find easily:

<td class="cellL"><input id="' . $r['code'] . '_category" type="text" style="width: 80px" name="category" value="' . $r['category'] . '"></td>
<td class="cellL"><input id="' . $r['code'] . '_type" type="text" style="width: 140px" name="type" value="' . $r['type'] . '"></td>
<td class="cellL"><input id="' . $r['code'] . '_size" type="text" style="width: 300px" name="size" value="' . $r['size'] . '"></td>

You're already calling an editId function when a cell is clicked, but looking at your data, $r['code'] is a string and your current code will not send it as a string. That will give an error, so we need to add quotation marks around it (since you're already using single quotes for your echo, we need to escape our new ones). Also, setting the onclick handler on a <td> is bad practice, it would be better to create a button for it:

<td class="buttonR"><button id="' . $r['code'] . '_button" type="button" onclick="editId(\'' . $r['code'] . '\');">' . $r['code'] . '</button></td>

Note: <button> elements have a default type of submit, which we don't want in this case. I added an id which we'll need later.

Step 2: Preparing your Javascript

Now that we have our HTML prepared, it's time to move on to the Javascript. I'm assuming you have jQuery available on your page.

Our JS function will need to accept one argument (the $r['code'] value for that row) and collect the values for that row into an object. It will then need to block the <input>s and the <button> so the user can't make any changes while PHP is busy, before sending the object to the server.

When the server responds, it will need to re-enable the <input>s and <button>. Now, if PHP successfully updated the data, no further action is needed. But if there was a problem, we'll want to alert the user that something went wrong.

<script type="text/javascript">
    function editId(code) {
        // get the button
        var button   = $('#' + code + '_button'),
            category = $('#' + code + '_category'),
            type     = $('#' + code + '_type'),
            size     = $('#' + code + '_size');

        // disable them all so the user can't interact anymore
        button.prop('disabled', true);
        category.prop('disabled', true);
        type.prop('disabled', true);
        size.prop('disabled', true);

        // build the object we're going to send to PHP
        var data = {
            "code":     code,
            "category": category.val(),
            "type":     type.val(),
            "size":     size.val()
        };

        // send the object to PHP
        $.post(
            '/update.php',
            data
        ).fail(function() {
            alert('Failed to update row ' + code);
        }).always(function() {
            // whether successful or failed, always re-enable the button and inputs
            button.prop('disabled', false);
            category.prop('disabled', false);
            type.prop('disabled', false);
            size.prop('disabled', false);
        });
    }
</script>

Step 3: Preparing your PHP

Note that in the Javascript function we're calling "/update.php". You can place name this PHP file wherever you want, just make sure the path in the Javascript function matches.

Our Javascript function is expecting an error if the update fails. That means sending a response header from PHP with a status code that's not in the 200-range. We'll be doing that with the header() function. The benefit of this method is that if we mess up our PHP code, the server will send a 500 internal server error, which our JS function will catch as well.

Our script is only going to try to update if all values are posted, so we need to check for that. Our JS is not going to do anything with the result, so we don't need to send any output. We're going to anyway, in case we need to do some debugging later. You can use your browser's network inspector to check the result you get from the AJAX call.

<?php
// I'm assuming your dbh_*** functions are somewhere in another PHP
// file you need to include here at the top. I'm also assuming
// dbh_get() returns a PDO database. If it returns a mysqli database,
// you'll need to change the binding of the parameters and the check
// for the number of affected rows accordingly.

// first make sure we're handling a POST request
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('HTTP/1.1 405 Method Not Allowed');
    echo 'Request method must be POST, this is a ' . $_SERVER['REQUEST_METHOD'] . ' request.';
    die();
}

// make sure all the properties we're expecting are submitted
$expected = array('code', 'category', 'type', 'size');
foreach ($expected as $property) {
    if (!isset($_POST[$property])) {
        header('HTTP/1.1 406 Not Acceptable');
        echo 'Missing a value for ' . $property;
        die();
    }
}

// now we can update our row in the database
$dbh = dbh_get();    

$sql = "
    UPDATE `table`
    SET    `category` = :category,
           `type`     = :type, 
           `size`     = :size
    WHERE  `code`     = :code
";

$stmt = $dbh->prepare($sql);
$stmt->execute(array(
    ':category' => $_POST['category'],
    ':type'     => $_POST['type'],
    ':size'     => $_POST['size'],
    ':code'     => $_POST['code']
));

if ($stmt->rowCount() == 0) {
    dbh_free($dbh);

    header('HTTP/1.1 204 No Content');
    echo "No changes were made, either there is no row with code '" . $_POST['code'] . "' or the values were the same as already stored.";
    die();
}

// no need to send a 'HTTP/1.1 200 OK' header, because that's the
// default response header sent by PHP. We also don't need to die()
// here, because this should be the last line in this file and
// it will stop automatically.
echo "Changes saved successfully";
miken32
  • 42,008
  • 16
  • 111
  • 154
rickdenhaan
  • 10,857
  • 28
  • 37
  • $r[code] is from the previous query it gives me the code... can I not reuse it? It works fine in the html part and I need it to update the correct row. This isn't my thing, I barely know what I'm doing – Kilisi May 20 '17 at 11:11
  • I see now that you're passing it via a Javascript onclick event handler: `onclick="editId(' . $r['code'] . ');"`. That means `editId` should be a Javascript function, not a PHP function. The Javascript function could then call a PHP file via AJAX to perform the update query. There are plenty of resources online to help you get started on that. – rickdenhaan May 20 '17 at 14:03
  • not getting anywhere so far, spent 4 solid hours trying different things, you're right it is a js function. I have seen websites that will create a dynamic table and allow you to edit rows, just can't find how they do it online – Kilisi May 20 '17 at 14:07
  • @Kilisi I've updated my answer to include a walkthrough of how to accomplish what you're trying to do. Let me know if that puts you on the right track. – rickdenhaan May 20 '17 at 18:54
  • This is very nice and after a bit of work I got it going. I can't use jquery on the live site unfortunately, but this gave me some ideas. Thanks mate. – Kilisi May 21 '17 at 00:05