skip to Main Content

I have a button that adds new fields to my form, ans another button that submits the value of the input fields to the server side (php).
I’m trying to get the best way to send values from dynamically created form input to php.

here is what i have tried

$('#submit').on("click", function(e) {
   e.preventDefault();
   for(var i = 1; i <= 9; i++) {

     if ($('label[name="men'+i+'"]').length) { //for each [i] check if man field exist 
       var manName  = $('select[id="manName'+i+'"]').val();
       var manAge  = $('select[id="manAge'+i+'"]').val();
       if (manName.length < 1) {
         //show input error on the form
       } else {
         //set value for each manName field created 
         window["manName" + i] = manName;
       }

       if (manAge.length < 1) {
         //show input error on the form
       } else {
         //set value for each manAge field created 
         window["manAge" + i] = manAge;
       }
     }
   } else {
     //if man field [i] was not created
     window["manName" + i] = "";
     window["manAge" + i] = "";
     //set man field [i] to empty/null
   }

 //and more of the above to check for women and children fields

}

then in my ajax i have

$.ajax
   ({
   type:"POST",
   url: "send.php",
   data: {"manName1": manName1, "manAge1": manAge1, "manName2": manName2, "manAge2": manAge2, "manName3": manName3, "manAge3": manAge3, "womanName1": womanName1, "womanAge1": womanAge1, "womanName2": womanName2, "womanAge2": womanAge2 }, //and so on for the rest of the women and children
    //cache: false,
    success: function(data) { 
    console.log(data)
    }
    });

this works, but freezes for a while before it responds.

So is there a proper way of doing this

2

Answers


  1. I think that primary freeze is caused by Uncaught RangeError: Maximum call stack size exceeded which means that somewhere in your code you made some infinite recursion calls.
    But maybe you should optimize your code to minimize DOM elements scaning with jQuery.

    1. Add some classname to every input’s group wrapper (assume .js-inputs-man) to get next HTML
    <div class="js-inputs-man">
        <select id="manName1"></select> 
        <select id="manAge1"></select> 
    </div>
    
    1. Apply next code to aggregate data. Do not use window as place to collect data.
    $('#submit').on('click', function(e) {
        e.preventDefault();
    
        var inputs = $('.js-input-man');
    
        if (input.length === 0) {
            //show input error on the form
        }
    
        var data = {}
    
        inputs.each(function (i, input) {
            var elem = $(input);
    
            data['manAge' + i] = elem.find('[id="manAge' + i +'"]').val();
            data['manName' + i] = elem.find('[id="mannName' + i +'"]').val();
        });
    
        // similar code for women and children which you can optimize too to not repeat it
    
        $.ajax({
            type:"POST",
            url: "send.php",
            data: data,
            success: function(data) { 
                console.log(data)
            }
        });
    }
    
    Login or Signup to reply.
  2. You probably have some kind of error in your for loop (maybe somewhere else in the code the value of i is changing, or you loop is calling another loop, etc)

    If you wanna find where it’s failing I suggest you to remove (or comment) pieces of code until it stops freezing. Then refactor the bad part until you find the bug.

    Here’s an example of how to achieve what you need without looping over the element’s ID. There’s nothing technically wrong with it, but ID purpose is to label unique elements. If you need more then one, you should use classes. This will avoid the index variable and lot’s of future trouble when the list itens are deleted.

    $('button.add').on('click', function (e) {
      e.preventDefault();
      var div = $('<div>');
      div.append('<h3 class="sex">'+this.id+'</h3>')
      div.append('<label class="name">name<input type="text" required></label>');
      div.append('<label class="age">age<input type="number" required></label>');
      var delBt = $('<button>X</button>');
      delBt.on('click', function () {
        $(this).parent().remove();
      });
      div.append(delBt);
      $('#inputContainer').append(div);
    });
    
    $('#submit').on('click', function (e) {
      e.preventDefault();
      var data = [];
      $('#inputContainer div').each(function () {
        var sex = $('.sex', this).text();
        var name = $('.name input', this).val();
        var age = $('.age input', this).val();
        data.push({sex, name, age});
      });
      console.clear();
      console.log(data);
    /*
      $.ajax({
        type:"POST",
        url: "send.php",
        data: data,
        success: function(data) {console.log(data)}
      });
    */
    });
    #inputContainer {
      padding: 1em;
    }
    input {
      width: 5em;
      margin: 0.5em;
    }
    input:invalid {
      border: 2px dashed red;
    }
    h3 {
      margin: 0;
    }
    <form>
      <button id="man" class="add">Add Man</button>
      <button id="woman" class="add">Add Woman</button>
      <button id="child" class="add">Add Child</button>
      <div id="inputContainer"></div>
      <input id="submit" type="submit" value="Submit">
    </form>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    If your list of inputs gets big enough (like over thousands of items) your users can experience some quick freezing since the JS main thread does block the UI.
    In this case you should use a timeout or animation frames to avoid UI blocking.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search