0

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!

3 Answers 3

2

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);


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

Comments

1

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.

8 Comments

Thank you! This is exactly what I was looking for. I'll do some research and practice with what you've given me here :). Everyone else had great answers, but @Timusan put the wording in a way that was easy to understand and explained best practice
you mean he gave a drop in solution?
onsubmit can't be a "real method" your terminology is off there. You might want to say that it's an existing function, which I believe. However you stil l shouldn't use the "onsubmit" html attribute to attach event handlers, you should instead use the addEventListener DOM method. Methods are those functions which are bound to an object. That is, their hidden this argument is other than the global, unless we are talking about the methods on the global. In any case, onsubmit is an attribute and not a method.
@user3172050 All of our answers contain decent information to solve pieces of your "puzzle". I thus highly suggest you also read both Ashnur's and Tobias' answer carefully to learn more about why your code did not function the way you wanted it to.
@Ashnur Since OP's question consisted not out of a single problem, but quite a few misconceptions (he asks Can someone help me figure this Javascript out?), the only logical thing to do was to give a working solution and explain each mistake that was made. Whether he uses it as a drop-in replacement is his decision, most importantly he now has enough handlebars to grasp on and learn from working example code. That would be the point of SO. And, as stated before, yours and Tobias' answer only contribute to that knowledge.
|
1

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.

2 Comments

Thank you! I'm pretty new to JS, so some of this stuff is confusing. Anyways, I'm logged off for tonight, but I'll follow your help and update with feedback and votes later today.
@user3172050 Sure thing buddy, let me know if you need any more help!

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.