How to access html form values from nested inputs

Viewed 1317

I'm trying to validate input from this form:

        <form id = "mpath" name = "mpath" action = './../cgitest.cgi' method="POST" onsubmit = "return validateForm(this)">

            Total Time (in ms): <input type = "text" name = "ttime">
            Number of Cars (1-10): <input type = "text" name = "carnum">
            Initial Speed (fps): <input type = "text" name = "initspeed"><br>

            <!--extraRowTemplate will be repeated for every change in the accleration of the
                head car -->
            <p class = "extraRowTemplate" name = "extraRowTemplate">
                Change:
                <select name="change">
                <option value="acc">Acceleration</option>
                <option value="dec">Deceleration</option>
                </select>

                Start time: <input type = "text" name="starttime">
                End time: <input type = "text" name="endtime">
                Amount (in fps): <input type = "text" name="amount"><br>
            </p>

            <div id = 'container'></div>

            <a href="#" id = "addRow"><i class="icon-plus-sign"></i>Add Change</a><br>

            <input type="submit" value="Load Head Car">
        </form>

Using this function (I haven't written any of the actual validation):

<script type="text/javascript">
        function validateForm(form){

            var tt = document.forms[0].ttime.value;
            var cn = document.forms[0].carnum.value;
            var is = document.forms[0].initspeed.value;
            var sta = form.elements[4].value;

            console.log(tt);
            console.log(cn);
            console.log(is);
            console.log(sta);


            if(tt == ""){
                alert("starttime must be filled out");
                return false;
            }

            //return false;
        }
    </script>

But when I try to submit values, it only finds the values for ttime, carnum, and initspeed, and not the value of starttime, endtime, or amount. Also, the value of change is always "acc", even if I set it to "deceleration".

For those wondering why I don't simply remove extraRowTemplate, I need to have those input options in a nested section because I have an option to duplicate them.

I've tried to pass the form as an argument to the function (as shown) as well as just use document.forms[0] to access it. Neither produce the correct result.

Also, when I remove the .value from the form.elements[4].value and set:

var sta = form.elements[4]; 

The console prints out:

 <input type = "text" name = "starttime">

Does anyone know how I can access the value of the nested inputs?

I suppose I should also say that the form works correctly in every other way, and when I send it to the cgitest.cgi, I can access all inputs. I just don't want to validate the inputs on the server side.

EDIT:

If instead of using an onsubmit function (validateForm in my case), I use an event listener:

<script type="text/javascript">
        var button = document.querySelector('input[type=submit]')

        button.addEventListener('click', function onClick(event) {
          var ttime = document.querySelector('input[name=ttime]')
          var carnum = document.querySelector('input[name=carnum]')
          var initspeed = document.querySelector('input[name=initspeed]')
          var change = document.querySelector('select[name=change]')
          var starttime = document.querySelector('input[name=starttime]')
          var endtime = document.querySelector('input[name=endtime]')
          var amount = document.querySelector('input[name=amount]')

          console.info('ttime', ttime.value)
          console.info('carnum', carnum.value)
          console.info('initspeed', initspeed.value)
          console.info('change', change.value)
          console.info('starttime', starttime.value)
          console.info('endtime', endtime.value)
          console.info('amount', amount.value)

          event.preventDefault()
        })
    </script>

With the input ttime = 1, carnum = 2, initspeed = 3, change = "acc", starttime = 4, endtime = 5, amount = 6, I get the following console output:

(index):70 ttime 1
(index):71 carnum 2
(index):72 initspeed 3
(index):73 change acc
(index):74 starttime 
(index):75 endtime 
(index):76 amount 

As can be seen, all values beyond initspeed (everything inside extraRowTemplate) are empty. Like I said before, they are not empty when sent to the form action url.

4 Answers

Can you try removing the extraRowTemplate and submit. If it's working, than you can try generating the elements inside with the different ids, because now you have duplicated items with no distinction.

You are currently accessing the elements in a bit of a roundabout way, using document.forms[0]. Also I don't see any code to get the value of the starttime input. You are testing tt in the if, but that was assigned the value of ttime.

document.querySelector

Might I suggest accessing the form elements by name directly, using document.querySelector? This method accepts a CSS selector and returns the first element that matches. Using a simple CSS3 selector we can select elements by name and assuming those names are unique on the page, we will get the right inputs. You could also use form.querySelector if the names are only unique within the form.

Example

var myInput = document.querySelector('input[name=ttime]')

I find document.querySelector and document.querySelectorAll (which gets all elements matching the CSS selector) very useful and use them all the time.

Runnable code snippet

Run this snippet and press the form submit button to print the values of the inputs. Try it and see how it works.

var button = document.querySelector('input[type=submit]')

button.addEventListener('click', function onClick(event) {
  var ttime = document.querySelector('input[name=ttime]')
  var carnum = document.querySelector('input[name=carnum]')
  var initspeed = document.querySelector('input[name=initspeed]')
  var change = document.querySelector('select[name=change]')
  var starttime = document.querySelector('input[name=starttime]')
  var endtime = document.querySelector('input[name=endtime]')
  var amount = document.querySelector('input[name=amount]')

  console.info('ttime', ttime.value)
  console.info('carnum', carnum.value)
  console.info('initspeed', initspeed.value)
  console.info('change', change.value)
  console.info('starttime', starttime.value)
  console.info('endtime', endtime.value)
  console.info('amount', amount.value)
  
  event.preventDefault()
})
<form id = "mpath" name = "mpath" action = './../cgitest.cgi' method="POST" onsubmit = "return validateForm(this)">

            Total Time (in ms): <input type = "text" name = "ttime">
            Number of Cars (1-10): <input type = "text" name = "carnum">
            Initial Speed (fps): <input type = "text" name = "initspeed"><br>

            <!--extraRowTemplate will be repeated for every change in the accleration of the
                head car -->
            <p class = "extraRowTemplate" name = "extraRowTemplate">
                Change:
                <select name="change">
                <option value="acc">Acceleration</option>
                <option value="dec">Deceleration</option>
                </select>

                Start time: <input type = "text" name="starttime">
                End time: <input type = "text" name="endtime">
                Amount (in fps): <input type = "text" name="amount"><br>
            </p>

            <div id = 'container'></div>

            <a href="#" id = "addRow"><i class="icon-plus-sign"></i>Add Change</a><br>

            <input type="submit" value="Load Head Car">
        </form>

I can access the value of your "starttime" field in Firefox/Chrome/Opera using either

var sta = document.forms[0][4].value

or

var sta = document.forms[0].starttime.value

I was able to figure out what was going wrong. In my css I set:

.extraRowTemplate {
     display: none;
}

which was preventing the input values from being sent. Once I removed this my problems went away. Setting "visibility : hidden" is a good alternative that allowed the values to be submitted and the template not visible.

Related