0

I'm looking for a way to submit multiple dynamic form fields in a single submission.
Each row of data when submitted will share certain attributes:
job id, client, type of work.
While also keeping their own independent variables:
role, name, tvl, start date, end date, start time, end time.

I think my solution will either require a for loop or the use of multi dimensional arrays (maybe both?) but I can't quite figure out where in my code to implement that or how to do so.

At the moment - only 1 "employee" is showing up in my database - typically the last entry made in the "details" div.

Here is the code:

HTML
index.php


<?php
  session_start();
?>

<!DOCTYPE html>
  <head>
  </head>
    <body>
        <form method="POST" action="include/ajax.inc.php" class="ajax">
                  <h2>Job Details</h2>
                  <br>
                  <div class="form-group row">
                    <label class="col-sm-2 col-form-label">Job ID</label>
                    <div class="col-sm-10">
                      <input type="text" class="form-control" name="a" id="a">
                    </div>
                  </div>

                  <div class="hr-line-dashed"></div>

                  <div class="form-group row">
                    <label class="col-sm-2 col-form-label">Client</label>
                    <div class="col-sm-10">
                      <select type="text" class="form-control" name="b" id="b">
                        <option value="" disabled selected>Select</option>
                        <option value="OPTION1" name="OPTION1">OPTION1</option>
                        <option value="OPTION2" name="OPTION2">OPTION2</option>
                        
                     
                      </select>
                    </div>
                  </div>

                  <div class="hr-line-dashed"></div>

                  <div class="form-group row">
                    <label class="col-sm-2 col-form-label">Type of Work</label>
                    <div class="col-sm-10">
                      <select type="text" class="form-control" name="c" id="c">
                        <option value="" disabled selected>Select</option>
                        <option value="OPTION1" name="OPTION1">OPTION1</option>
                        <option value="OPTION2" name="OPTION2">OPTION2</option>
                      
                      </select>
                    </div>
                  </div>

                  <div class="hr-line-dashed"></div>

                  <h2>Employee Details</h2>
                  <button class="btn btn-lg btn-primary btn-rounded m-sm" id="add">
                    <small>ADD EMPLOYEE</small>
                  </button>
                  <!--- ADD EMPLOYEES --->
                  <div class="ibox" id="details" name="details[]">
                    <div class="ibox-content">
                      <div class="container">
                        <div class="row">
                          <div class="col">
                            <label class="form-label">Position</label>
                            <select class="form-control" type="text" name="d" id="d">
                              <option value="" disabled selected>Select</option>
                              <option value="ROLE1" name="SPV">ROLE1</option>
                              <option value="ROLE2" name="REG">ROLE2</option>
                            </select>
                          </div>

                          <div class="col">
                            <label class="form-label">Name</label>
                            <input type="text" class="form-control" name="e" id="e">
                          </div>

                          <div class="col">
                            <label class="form-label">TVL</label>
                            <input type="text" class="form-control" name="f" id="f">
                          </div>

                          <div class="col">
                            <label class="form-label">Start Date</label>
                            <input type="date" class="form-control" name="g" id="g">
                          </div>

                          <div class="col">
                            <label class="form-label">End Date</label>
                            <input type="date" class="form-control" name="h" id="h">
                          </div>

                          <div class="col">
                            <label class="form-label">Start Time</label>
                            <input type="time" class="form-control" name="i" id="i">
                          </div>

                          <div class="col">
                            <label class="form-label">End Time</label>
                            <input type="time" class="form-control" name="j" id="j">
                          </div>
                          <div class="col text-right m-t-lg">
                          </div>

                        </div>
                      </div>
                    </div>
                  </div>
                  <!--- ADD EMPLOYEES END --->
                  <div class="hr-line-dashed"></div>
                  <button type="submit" class="btn btn-primary btn-med" name="submit">Submit</button>
                </form>
<!-- SCCRIPT-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="js/main.js"></script>
  </body>
  </html>

JS
main.js

$(document).ready(function(){

  var html = ' <div class="ibox" id="details" name="details[i]"> <div class="ibox-content"> <div class="container"> <div class="row"> <div class="col"> <label class="form-label">Position</label> <select class="form-control" type="text" name="d" id="d"> <option value="" disabled selected>Select</option> <option value="SPV" name="SPV">SPV</option> <option value="REG" name="REG">REG</option> </select> </div> <div class="col"> <label class="form-label">Name</label> <input type="text" class="form-control" name="e" id="e"> </div> <div class="col"> <label class="form-label">TVL</label> <input type="text" class="form-control" name="f" id="f"> </div> <div class="col"> <label class="form-label">Start Date</label> <input type="date" class="form-control" name="g" id="g"> </div> <div class="col"> <label class="form-label">End Date</label> <input type="date" class="form-control" name="h" id="h"> </div> <div class="col"> <label class="form-label">Start Time</label> <input type="time" class="form-control" name="i" id="i"> </div> <div class="col"> <label class="form-label">End Time</label> <input type="time" class="form-control" name="j" id="j"> </div> <div class="col text-right m-t-lg"> </div> <div class="col text-right m-t-lg"> <button class="btn btn-sm btn-rounded btn-danger" id="remove"> <i class="fa fa-times"></i> </button> </div></div> </div> </div> </div>'

  // Add rows to the form
    $(function() {
    $('#add').click(function(e) {
      $('#details').append(html);
      e.preventDefault();
      });

   // Remove rows from the form 
    $(this).on('click', '#remove', function(e) {
    $(this).closest('#details').remove();
    });

  });


});


$('form.ajax').on('submit', function() {

  var that = $(this),
    url = that.attr('action'),
    type = that.attr('method'),
    data = {};

    that.find('[id]').each(function(index, value){
      var that = $(this),
      name = that.attr('id'),
      value = that.val();
      data[name] = value;

    });

  $.ajax ({
    url: url,
    type: method,
    data: data,
    success: function(response) {
    console.log(response);
    }


  });

  return false;

});

PHP
ajax.inc.php

<?php
    include 'form.dbh.php'; {

    
    $jobid = mysqli_real_escape_string($conn,$_POST['a']);
    $client = mysqli_real_escape_string($conn,$_POST['b']);
    $type = mysqli_real_escape_string($conn,$_POST['c']);
    $role = mysqli_real_escape_string($conn,$_POST['d']);
    $name = mysqli_real_escape_string($conn,$_POST['e']);
    $tvl = mysqli_real_escape_string($conn,$_POST['f']);
    $sdate = mysqli_real_escape_string($conn,$_POST['g']);
    $edate = mysqli_real_escape_string($conn,$_POST['h']);
    $stime = mysqli_real_escape_string($conn,$_POST['i']);
    $etime = mysqli_real_escape_string($conn,$_POST['j']);



    $sql = "INSERT INTO timesheets(jobid, client, type, role, name, tvl, sdate, edate, stime, etime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
    $stmt = mysqli_stmt_init($conn);
    if (!mysqli_stmt_prepare($stmt, $sql)){
      echo "SQL error";
    } else {
      mysqli_stmt_bind_param($stmt, 'ssssssssss', $jobid, $client, $type, $role, $name, $tvl, $sdate, $edate, $stime, $etime);
      mysqli_stmt_execute($stmt);

  }

  header("Location:../index.php?success");
  }

 ?>

Does anyone have an idea? or any suggestions?

4
  • Welcome to Stack Overflow. With Form Submissions, you will want to prevent the default action when you are performing AJAX calls. It would best to add an event variable, e and then call .preventDefault() in the callback. Commented Oct 11, 2020 at 23:27
  • Also I see that you have that being used twice in the same callback. It should be separated, yet it might be ambiguous enough that it overwrites the original that. As a rule of thumb, use unique variable names when possible. Commented Oct 11, 2020 at 23:33
  • Please provide more insights - which part of your application is not working as expected? It's very unlikely that your problem covers Javascript, PHP, HTML, jQuery and SQL, all in once Commented Oct 12, 2020 at 7:22
  • I'm looking to submit multiple appended entries in a single submit function- at the moment only one entry(the last child) is being submitted while the other appended entries, including the parent entry are not being submitted. Commented Oct 12, 2020 at 15:20

1 Answer 1

1

Consider the following.

$(function() {

  var html = ' <div class="ibox" id="details" name="details[i]"> <div class="ibox-content"> <div class="container"> <div class="row"> <div class="col"> <label class="form-label">Position</label> <select class="form-control" type="text" name="d" id="d"> <option value="" disabled selected>Select</option> <option value="SPV" name="SPV">SPV</option> <option value="REG" name="REG">REG</option> </select> </div> <div class="col"> <label class="form-label">Name</label> <input type="text" class="form-control" name="e" id="e"> </div> <div class="col"> <label class="form-label">TVL</label> <input type="text" class="form-control" name="f" id="f"> </div> <div class="col"> <label class="form-label">Start Date</label> <input type="date" class="form-control" name="g" id="g"> </div> <div class="col"> <label class="form-label">End Date</label> <input type="date" class="form-control" name="h" id="h"> </div> <div class="col"> <label class="form-label">Start Time</label> <input type="time" class="form-control" name="i" id="i"> </div> <div class="col"> <label class="form-label">End Time</label> <input type="time" class="form-control" name="j" id="j"> </div> <div class="col text-right m-t-lg"> </div> <div class="col text-right m-t-lg"> <button class="btn btn-sm btn-rounded btn-danger" id="remove"> <i class="fa fa-times"></i> </button> </div></div> </div> </div> </div>'


  $('#add').click(function(e) {
    $('#details').append(html);
    e.preventDefault();
  });

  // Remove rows from the form 
  $(this).on('click', '#remove', function(e) {
    $(this).closest('#details').remove();
  });

  $('form.ajax').on('submit', function(e) {
    e.preventDefault();

    var that = $(this),
      u = that.attr('action'),
      t = that.attr('method'),
      d = {};

    that.find('[id]').each(function(i, el) {
      d[$(el).attr("id")] = $(el).val();
    });

    $.ajax({
      url: u,
      type: t,
      data: d,
      success: function(response) {
        console.log(response);
      }
    });

    return false;
  });
});

This cleans up some of the issues you are seeing. When using .each() you will have an Index and Element, not a Value.

Update

The code above will submit all data based on the form.ajax selector. When you have only one section of details in the form, that is all the data that will be submitted. If you add your HTML, you cause an HTML/JS issue where the ID attributes of the elements are no longer Unique. All IDs must be unique.

Consider ignoring the IDs and make use of name attribute instead. When you gather the data, for d through j, these would need to be Arrays, since these are the items that repeat.

Consider the following.

$(function() {
  function getData(f) {
    var myData = {
      a: $("[name='a']", f).val(),
      b: $("[name='b']", f).val(),
      c: $("[name='c']", f).val(),
      d: [],
      e: [],
      f: [],
      g: [],
      h: [],
      i: [],
      j: []
    };
    var k, v;
    $("[name]", f).each(function(i, el) {
      k = $(el).attr("name");
      v = $(el).val();
      if (i > 2) {
        myData[k].push(v);
      }
    });
    console.log(myData);
    return myData;
  }

  $('#add').click(function(e) {
    var html = $("#details > .ibox-content:eq(0)").clone(true);
    $(".col:last", html).html("<button class='btn btn-sm btn-rounded btn-danger remove' id='remove-" + $(".ibox-content").length + "'> <i class='fa fa-times'></i> </button>");
    $(".ibox-content:last").after(html);
    e.preventDefault();
  });

  $("#details").on('click', '.remove', function(e) {
    $(this).closest('.ibox-content').remove();
  });

  $("form.ajax").submit(function(e) {
    e.preventDefault();
    $.ajax({
      url: $(this).attr("action"),
      type: "POST",
      data: getData(this),
      success: function(response) {
        console.log(response);
      }
    });
  });
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="POST" action="include/ajax.inc.php" class="ajax">
  <h2>Job Details</h2>
  <br>
  <div class="form-group row">
    <label class="col-sm-2 col-form-label">Job ID</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" name="a" id="a">
    </div>
  </div>

  <div class="hr-line-dashed"></div>

  <div class="form-group row">
    <label class="col-sm-2 col-form-label">Client</label>
    <div class="col-sm-10">
      <select type="text" class="form-control" name="b" id="b">
        <option value="" disabled selected>Select</option>
        <option value="OPTION1">OPTION1</option>
        <option value="OPTION2">OPTION2</option>
      </select>
    </div>
  </div>

  <div class="hr-line-dashed"></div>

  <div class="form-group row">
    <label class="col-sm-2 col-form-label">Type of Work</label>
    <div class="col-sm-10">
      <select type="text" class="form-control" name="c" id="c">
        <option value="" disabled selected>Select</option>
        <option value="OPTION1">OPTION1</option>
        <option value="OPTION2">OPTION2</option>
      </select>
    </div>
  </div>

  <div class="hr-line-dashed"></div>

  <h2>Employee Details</h2>
  <button class="btn btn-lg btn-primary btn-rounded m-sm" id="add"><small>ADD EMPLOYEE</small></button>
  <!--- ADD EMPLOYEES --->
  <div id="details" class="ibox">
    <div class="ibox-content">
      <div class="container">
        <div class="row">
          <div class="col">
            <label class="form-label">Position</label>
            <select class="form-control" type="text" name="d" id="d">
              <option value="" disabled selected>Select</option>
              <option value="ROLE1">ROLE1</option>
              <option value="ROLE2">ROLE2</option>
            </select>
          </div>

          <div class="col">
            <label class="form-label">Name</label>
            <input type="text" class="form-control" name="e" id="e">
          </div>

          <div class="col">
            <label class="form-label">TVL</label>
            <input type="text" class="form-control" name="f" id="f">
          </div>

          <div class="col">
            <label class="form-label">Start Date</label>
            <input type="date" class="form-control" name="g" id="g">
          </div>

          <div class="col">
            <label class="form-label">End Date</label>
            <input type="date" class="form-control" name="h" id="h">
          </div>

          <div class="col">
            <label class="form-label">Start Time</label>
            <input type="time" class="form-control" name="i" id="i">
          </div>

          <div class="col">
            <label class="form-label">End Time</label>
            <input type="time" class="form-control" name="j" id="j">
          </div>
          <div class="col text-right m-t-lg">
          </div>

        </div>
      </div>
    </div>
  </div>
  <!--- ADD EMPLOYEES END --->
  <div class="hr-line-dashed"></div>
  <button type="submit" class="btn btn-primary btn-med">Submit</button>
</form>

You may notice, only specific elements have the name attribute now. DIV elements should not use name and the same goes for OPTION. DIV is not a part of a Form. OPTION is a element part of SELECT which is the parent container and the form element, this should have name.

Your PHP will get a complex payload of data. For example:

{
  "a": "2020",
  "b": "OPTION1",
  "c": "OPTION2",
  "d": [
    "ROLE1",
    "ROLE2"
  ],
  "e": [
    "Bob",
    "Nancy"
  ],
  "f": [
    "1",
    "2"
  ],
  "g": [
    "2020-10-12",
    "2020-10-12"
  ],
  "h": [
    "2020-10-16",
    "2020-10-16"
  ],
  "i": [
    "08:00",
    "08:00"
  ],
  "j": [
    "12:00",
    "12:00"
  ]
}

You will need to adjust your PHP to handle this new data format.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! This cleans it up nicely but I still have the issue of only 1 entry being submitted into the database. I would like to submit more than one entry upon the submit click, should this be done with a forloop?
Edit: To clarify - this edit has allowed me to "submit" the next entry, which is a huge improvement but I believe what I'm trying to do is "submit" all entries - at once rather than in succession of each other
@jadew I am glad it did. If it answers your question, I hope you will Mark it as the Answer as well as Upvote.
will do! One last question - as I add a new element/variable in var myData I'm facing an error. For instance, I want to add another variable above a: $("[name='a']", f).val(), named id: $("[name='id']", f).val(), (following the same rules as variables a,b,c) When I do this myData[k].push(v); and var k,v; become unidentifiable. Can you suggest why that is and what the solution may be?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.