0

I'm creating a page to input my student's result but it only saved one student's result instead on all students in the list. I used javascript to auto-save/update input value. I created a loop for fetch.php and it saves all students at once without using JavaScript. I need help on the script so I can save all students result at once

function autosave() {
  var title = $("#post_title").val();
  var desc = $("#post_desc").val();
  var id = $("#post_id").val();


  if (title != " " && desc != " ") {
    $.ajax({
      url: "fetch.php",
      method: "POST",
      data: {
        send_title: title,
        send_desc: desc,
        send_id: id
      },
      dataType: "text",
      success: function(data) {
        if (data != "") {
          $("#post_id").val(data);
        }

        $("#autosave").text("Data saved");
      } /* success */
    }) /* ajax */
  } /* filter */

} /* autosave */

setInterval(function() {
  autosave();
  setInterval(function() {
    $("#autosave").text("");
  }, 5000)

}, 10000)
<?php $results = mysqli_query($conn,"SELECT * FROM student LIMIT 5");
    while($rows = mysqli_fetch_array($results)) { ?>
<tr>
  <td>
    <?php echo $rows['fname'].' '.$rows['lname']?>
  </td>
  <td><input type="text" class="form-control" id="post_title" name="post_title[]"></td>
  <td><input type="text" class="form-control" id="post_desc" name="post_desc[]"></td>
  <input type="hiden" class="form-control" value="<?php echo $rows['idnumber'] ?>" id="post_id" placeholder="hidden ID value" name="post_id[]">
  <?php } ?>

  <div id="autosave"></div>

About is the index file that call for all students and I can input score for each. Below is also fetch.php to save data into db.

$N = count($st);
for($i=0; $i < $N; $i++) {
  $st = $_POST["send_id"];
  $fa1 = $_POST["send_title"][$i];
  $fa2 = $_POST["send_desc"][$i];
  $r = mysqli_query($conn, "SELECT * FROM tbl_data WHERE idnumber='$st[$i]'");
  // GET THE NUMBER OF ROWS RETURNED:
  $rows = @mysqli_num_rows($r);
  if ($rows === 0) {  
    $sql = "INSERT INTO tbl_data (post_title, post_desc, idnumber)
      VALUES ('".$_POST["send_title"]."','".$_POST["send_desc"]."','$st[$i]')";
    mysqli_query($conn, $sql);
    //echo mysqli_insert_id($conn);
  } else{
    $sql = "UPDATE tbl_data SET post_title='".$_POST["send_title"]."', 
      post_desc='".$_POST["send_desc"]."' where idnumber = '$st[$i]'";
    mysqli_query($conn, $sql);
  }
mplungjan
  • 169,008
  • 28
  • 173
  • 236
sammyltk
  • 23
  • 6
  • Please visit [help], take [tour] to see what and [ask]. Do some research, search for related topics on SO; if you get stuck, post a [mcve] of your attempt, noting input and expected output, preferably in a [Stacksnippet](https://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/) – mplungjan Aug 05 '23 at 13:31
  • 1
    1. IDs must be unique. 2. Why are you using interval to save students? To save while they type? – mplungjan Aug 05 '23 at 13:32
  • **Warning:** You are wide open to [SQL Injections](https://php.net/manual/en/security.database.sql-injection.php) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/32391315) – Dharman Aug 05 '23 at 13:36

2 Answers2

2

You are including HTML nodes with repeated IDs in your DOM, which may lead to inconsistent data when working with JavaScript. It's important to avoid using duplicate IDs on a same DOM.

To achieve what you want in a simpler and more organized manner, I recommend using a <form> wrapped around your <table> and then serializing the form using the jQuery serializeArray function. This way, you can easily collect the form data and send it as the data payload in your AJAX request to the backend.

For instance, you can name your input fields in the form as follows:

<input type="text" name="post_title[<?php echo $i?>]['post_title']" value="...">
<input type="text" name="post_title[<?php echo $i?>]['post_desc']" value="...">
<input type="hidden" name="post_title[<?php echo $i?>]['post_id']" value="<?php echo $post_id ?>">

When you submit the form, the data will be serialized in a structured manner based on the input names, making it easier to handle in the backend. For example, on the backend, you will receive the data somewhat like this:

Array
(
    [0] => Array
        (
            [post_title] => First Title
            [post_desc] => First Description
            [post_id] => 1
        )

    [1] => Array
        (
            [post_title] => Second Title
            [post_desc] => Second Description
            [post_id] => 2
        )

)

This will allow you to process the data efficiently on the server-side and avoid complications due to duplicate IDs in the DOM.

0

You can collect your form-control data into an array:

let data = [];
for (let tr of document.querySelectorAll('form tr')) {
    let formControls = tr.querySelectorAll(".form-control");
    data.push({
        send_id: formControls[2],
        send_title: formControls[0],
        send_desc: formControls[1],
    });
}

and then pass this data when you call your $.ajax.

Explanation:

  • we get all tr elements inside form elements. You may want to adjust the selector
  • we loop the trs
    • we get the form controls inside the current tr
    • we build an object containing the fields we desire and push it into data

The problem in your current code is that you get unique elements by id. Instead, we need to find all rows.

Further notes:

  • you should not duplicate ids, they are meant to be unique
  • you need to adjust your server-side code, change $_POST["send_id"] to $_POST["send_id"][$i], so you will save the changes for the correct user
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175