简体   繁体   中英

How can I dynamically generate input fields with Javascript and then use their values?

I'd like to be able to find the number value of the courseAmount input field upon submit, and then generate new input fields (into the hourForm form underneath the initialForm ) through the onsubmit method in javascript, and then retrieve the value from each of the generated input fields upon the submission of the hourForm form and place those values into an array.

However, I'm having difficulty with actually generating the input fields with javascript, and I suspect that I'm having difficulty with retrieving the value of the courseAmount input and porting that to my createInput() function, but I'm not exactly sure if that's the issue.

Here's my HTML:

<!DOCTYPE html>
<head>
  <link rel="stylesheet" href="css/main.css">
</head>
<body>
  <form id="initialForm" method="post" onsubmit="createInput()" action="">
    <label>Number of hours for which you would like to study</label>
    <input type="number" name="overallHours" id="overallHours" class="stored" min="1" max="20" step="1" value="1"/>
    <label>Number of courses you would like to study for</label>
    <input type="number" name="courseAmount" id="courseAmount" class="stored" min="1" max="20" step="1" value="1"/>
    <input type="submit" class="submitStudy" value="Submit"/>
  </form>
  <form id="hourForm" method="post" onsubmit="calcHours">
    <label>State the desired time spent working in each course</label>
  </form>
</body>

And here's my Javascript:

var notedOverallHours = document.getElementById("overallHours").value * 60; 
var courseNumberTotal = document.getElementById("courseAmount").value;
var counter = 0;

function createInput() {
  var newForm = document.getElementById("hourForm");
  document.getElementById("initialForm").style.display = "none";
  document.getElementById("hourForm").style.display = "block";

  for (i = 0; i <= courseNumberTotal; i++) {
    newForm.innerHTML = "<label>Course #" + (counter + 1) + "</label>" + "<input type='number' name='courseHours' class='newInputs' min='1' max='9' step='1' value='1'/>";
    counter++;
  }
  newForm.innerHTML = "<input type='submit' value='submit'/>";
}

Can someone help me figure this Javascript out? My JSFiddle attempts have been futile because JSFiddle does not take kindly to forms reloading the page.

Thank you!

From the mdn page about innerHTML: "Removes all of element's children, parses the content string and assigns the resulting nodes as children of the element." https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML

Generally speaking you do not want to use innerHTML at all. There is almost always a better approach. In this case this will be createElement and appendChild.

Furthermore, there is no such thing as "onsubmit" method. What you are calling like that is an HTML attribute which registers a handler for the submit event. http://www.quirksmode.org/js/introevents.html

However using html attributes has its serious drawbacks: http://www.quirksmode.org/js/events_advanced.html

Considering all that, here is what I would do: http://jsfiddle.net/ashnur/rwod4z1d/

HTML:

<form id="initialForm" method="post" action="">
    <label>Number of hours for which you would like to study</label>
    <input type="number" name="overallHours" id="overallHours" class="stored" min="1" max="20" step="1" value="1" /><hr>
    <label>Number of courses you would like to study for</label>
    <input type="number" name="courseAmount" id="courseAmount" class="stored" min="1" max="20" step="1" value="1" /><hr>
    <input type="submit" class="submitStudy" value="Submit" />
</form>
<form id="hourForm" method="post" >
    <label>State the desired time spent working in each course</label><hr>
</form>

js:

var notedOverallHours = document.getElementById("overallHours").value * 60;
var courseNumberTotal = document.getElementById("courseAmount").value;
var counter = 0;

var initialForm = document.getElementById("initialForm");
var hourForm = document.getElementById("hourForm");

initialForm.addEventListener('submit', createInput);
hourForm.addEventListener('submit', calcHours);

function calcHours() {}

function createInput(ev) {
    ev.preventDefault(); // this is not needed if you are using a bare button and the click event
    var newForm = document.getElementById("hourForm");
    initialForm.style.display = "none";
    hourForm.style.display = "block";

    for (i = 0; i <= courseNumberTotal; i++) {
        addControl(newForm, "Course #" + (counter + 1));
        counter++;
    }
    var submit = document.createElement('input');
    submit.type = 'submit';
    submit.value = 'submit';
    newForm.appendChild(submit);
}

function addControl(form, labelText) {
    var label = document.createElement('label');
    var input = document.createElement('input');
    var hr = document.createElement('hr');
    input.type = 'number';
    input.name = 'courseHours';
    input.classname = 'newInputs';
    input.min = '1';
    input.max = '9';
    input.step = '1';
    input.value = '1';
    label.textContent = labelText;
    form.appendChild(label);
    form.appendChild(input);
    form.appendChild(hr);


}

When the createInput() function is called you are not having the desired results because you are reseting the newForm.innerHTML in each iteration of the loop and then again at the end. Rather than using = you should be using += to append the desired text rather than replace the existing text.

// Replacing the contents of newForm.innerHTML
newForm.innerHTML = "foo";

// Appending to newForm.innderHTML (You want to do this)
newForm.innerHTML += "foo";

Another problem is that when you press submit the page is reloading before createInput() is able to have the desired result. You most likely want to stop the page actually submitting and thus reloading when you press the submit button. To do this you can change the onsubmit attribute for the form to "return createInput()" and then add the line return false; to the end of the createInput() function to indicate to the browser that you do not wish to submit the form.

As Tobias correctly pointed out, your form submission event is allowed to continue which results in a page refresh and a "reset" of all plain JavaScript data. Furthermore, you are not capturing your values ( notedOverallHours and courseNumberTotal ) on form submission (after the user has entered an amount), but rather when your page initializes ( before the user has input anything).

So, to go about fixing this, first a tiny modification to your HTML:

...
<form id="initialForm" method="post" action="">
...

Notice that I deleted the onsubmit attribute from your form. We can capture that with an event in JavaScript itself.

Next attach an event listener to your form which prevents it from submitting and calls your createInput() function:

document.getElementById("initialForm").addEventListener('submit', function (e) {
  e.preventDefault();
  createInput();
});

This will attach an eventListener that listens to the submit event on your initialForm element. The first parameter is the type of event you want to listen for ( submit in this case), the second is the callback you want to have fired.

The callback function always gets the event passed in (the e argument). By calling preventDefault on this event we can stop it from bubbling up and actually causing a page refresh.

Next we call the createInput() function which, after some modifications, looks like this:

function createInput() {
  var notedOverallHours = document.getElementById("overallHours").value * 60; 
  var courseNumberTotal = document.getElementById("courseAmount").value;
  var newForm = document.getElementById("hourForm");

  document.getElementById("initialForm").style.display = "none";
  document.getElementById("hourForm").style.display = "block";

  // Add our elements
  for (i = 1; i <= courseNumberTotal; i++) {
    var child = document.createElement('li');
    child.innerHTML = "<label>Course #" + (i) + "</label>" + "<input type='number' name='courseHours-"+ i+"' class='newInputs' min='1' max='9' step='1' value='1'/>";
    newForm.appendChild(child);
  }

  // Add our button
  var button = document.createElement('li');
  button.innerHTML = "<input type='submit' value='submit'/>";
  newForm.appendChild(button);
}

As you can see, I capture the notedOverallHours and courseNumberTotal variables inside the createInput() function, so they will carry whichever value was set during the form submission event.

Then we iterate over each course number. Instead of replacing the innerHTML , we first create an element ( li in our case) and fill that element with a HTML string. Next we append this child element to the parent form.

Inside the loop I have removed the counter variable as you can simply use the value of i inside the loop, no need to create an extra variable. I also appended the name attribute for each child with i , so not to get any name clashes.

At the end of our function we simply create and append a new li element containing the submit button.

You can optimize this further by actually creating the label and input elements with the createElement function and set its attributes and text individually with plain JavaScript setters, instead of dumping everything inside li elements as I've done here to keeps things a bit more simple for now. I`ll leave that up as an exercise :)

I have created a rough JSFiddle with this exact code here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM