0

My website has a bunch of rows (as many as the user needs) consisting of two fields. I want the user to fill in all the fields, and submit them. However, I believe this can all be handled client-side, since I want to use the field values in javascript code.

this is the html code:

<div class="players">
  <div id="wrapper">
    <span>Name: <input type="text"> Dex modifier:  <input type="text"></span>
  </div>

  <input type="button" value="add player" onclick="add_fields()">
  <input type="button" value="submit" onclick="submit()">

</div>

and my javascript function

function add_fields() {
  document.getElementById("wrapper").innerHTML += '<br><span>Name: <input type="text"> Dex modifier:  <input type="text"></span>\r\n'
}

I need a way to get all of the form values (right now with an unwritten function submit()) and store them as variables.

sebastienbarbier
  • 6,542
  • 3
  • 29
  • 55
avalc
  • 68
  • 6
  • If you want to perform validation client side then you do NOT need to wrap anything in a form, a form just allows you to group inputs for submission to a server using either the GET or POST method. Accessing and Validating locally is easy using document.getElementByID, but check the return from the function before using and never assume the return will always be valid. For you text input,add and attribute to assign an ID to the tag then use the ID in your getElementbyID. – SPlatten Aug 15 '19 at 09:12
  • Although it is true that a form is not needed, it does makes your code dynamic. So you would be able to add additional inputs without altering your JS code. – Emiel Zuurbier Aug 15 '19 at 09:22

2 Answers2

0

You need to be able to get the values of the dynamically added input elements.

First, you need to add them in a way you can separate them. So, providing each pair an exclusive parent is necessary.

document.getElementById("wrapper").innerHTML += '<div id="aparent"><br><span>Name: <input type="text" id="name"> Dex modifier:  <input type="text" id="dex"></span><div>\r\n'

Now, get all the parent elements and iterate through them to fill an array of "name" and "dex-modifier" pairs. Use a library like JQuery for easy DOM manipulation. This seems to be your "submit" function.

var userData = [];

//Iterate all the parents
$('#aprane').each(function() {

    //Get the values of each pair and put them in an array
    userData.push({name: $(this).children('#name').val(), dex: $(this).children('#dex').val()}

})
Charlie
  • 22,886
  • 11
  • 59
  • 90
0

It is good practice to use a <form> element when handling multiple inputs simultaneously. The form element can access all of the inputs it has inside of it. This way you won't have to select each individual input but can select and process them all together.

So start with the form wrapping. Then instead of listening for the onclick on the <input type="button" value="submit" onclick="submit()">, listen for the submit event on the form element.

It is considered best practice to listen to events by using the .addEventListener() method. This way you can set multiple event handlers to a single event without overwriting the onclick or onsubmit property of an element. Chris Baker does an excellent job explaining it in this SO post.

So now that you have a form, how do we get the data out of it? You could use the modern class of FormData. FormData creates an iterable object, which means we can loop over it using for..of, that holds all the names and values of the inputs in a form. It also has methods to add, remove and get the keys or values from the object. The FormData constructor can take a <form> element as argument like so:

var formElement = document.querySelector('form'); // Select the form.
var formData = new FormData(form); // Pass the form into the FormData class.

Now the formData variable holds all of the names and values of the form.

I've added a working example for you to try out. Please read up on the documentation I provided you to understand what is going on and what you can do with it.

Quick sidenote: FormData and the for..of loop are relatively new and are not supported in IE. If that is a dealbreaker I would suggest you don't use the FormData constructor and simply loop over the elements within the form.

Edit: I changed to loop from formData.values() to formData to get both the name and value attributes of each input. This is identical to formData.entries() as show in the MDN documents.

// Create storage for the values.
var values = [];

// Get the form element.
var form = document.getElementById('form');

// Add the submit event listener to the form.
form.addEventListener('submit', submit);

function submit(event) {

  // Get the data from the form.
  // event.target represents the form that is being submitted.
  var formData = new FormData(event.target);
  
  // Loop over each pair (name and value) in the form and add it to the values array.
  for (var pair of formData) {
    values.push(pair);
  }
  
  // Log the values to see the result.
  console.log(values);
  
  // Prevent the form from default submitting.
  event.preventDefault();
}
<div class="players">

  <!-- Wrap a form around the inputs -->
  <form id="form">
  
    <div id="wrapper">
      <span>Name: <input type="text" name="name"> Dex modifier:  <input type="text" name="dex"></span>
    </div>

    <input type="button" value="add player" onclick="add_fields()">

    <!-- Notice type="submit" instead of type="button". This is important -->
    <input type="submit" value="submit">
    
  </form>
  
</div>
Emiel Zuurbier
  • 19,095
  • 3
  • 17
  • 32
  • I was using the form element before but I stopped because I thought it had to pass the data to the server side. I guess 'event.preventDefault();' stops this from happening, and whenever the listener catches a client submitting, then it pushes the form data to the 'values' list? – avalc Aug 15 '19 at 08:33
  • That is correct. Without `event.preventDefault()` the data is send to the server. And yes, the function loops over each value in the form and adds it to the `values` array. Notice that when you repeatedly submit the form it keeps adding the values. – Emiel Zuurbier Aug 15 '19 at 08:39
  • I've updated the loop so it will not only show the value, but also the name that represents the value. – Emiel Zuurbier Aug 15 '19 at 09:04