0

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

  • In what way does it "freeze"? Is the server taking a long time to respond? Or is the client-side code locking the browser for a few moments? – David Dec 20 '19 at 12:37
  • yes the client-side, with this error in the browser console "Uncaught RangeError: Maximum call stack size exceeded" – Otun Musa Bashir Dec 20 '19 at 12:49
  • 1
    It means that somewhere in your code you made some infinite recursion calls. You can put a breakpoint in function which call causes this error to find out where is the trouble. – wmbtrmb Dec 20 '19 at 12:52

2 Answers2

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)
        }
    });
}
wmbtrmb
  • 307
  • 1
  • 17
1

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.

rafaelcastrocouto
  • 11,781
  • 3
  • 38
  • 63