1

I have some JavaScript/jQuery that I am trying to run locally for testing. It begins with $( 'form' ).submit(function(event) {, but, never gets beyond that. (I put a console.log just after that line. It never executes. I know the js is being executed because a console.log before that line does execute.) A syntax checker gives no errors.

JavaScript:

$( 'form' ).submit(function(event) {
 const SelectElms = $( 'select' );
  var  a          = [];
  var  selectVals = Array.from(SelectElms).reduce((a,n) => {
    if(n.value && n.value !== 'unsure' && n.value !== 'not attend') {
      a.push( {
                 'index': n,
                 'room': n.value
              }
            );
    }  // end if
    return a;
  });  //  end def arrow fn & reduce
  event.preventDefault();
});  //  end def anonymous fn & submit

In the snippet below, the form displays correctly, but, on submit, the console flashes an error message for a second, then disappears. It displays for too little time to read it. Then, the error message "The custom error module does not recognize this error" appears in the results pane.

Also, if you would, please check the rest of the js for correctness. What I want to do is create an array of objects, one object per <select> element in the form. Each object should have the index position of and the value of the <select> element ({'index': n, 'room': n.value}).

In his answer to this prior question, MisterJojo did something similar which I tried to run locally. Although it runs in his snippet, when I run it locally, it produces a TypeError that the querySelector('#My-Form') returns null. I copied and pasted his js and HTML. The form has id="My-Form" in the <form> tag. Also, the syntax checker returns several errors. So, I haven't been able to implement his solution or adapt it to this problem. Note: it does run in this jsfiddle.

Thanks so much for your help.

Snippet:

$( 'form' ).submit(function(event) {
 const SelectElms = $( 'select' );
  var  a          = [];
  var  selectVals = Array.from(SelectElms).reduce((a,n) => {
    if(n.value && n.value !== 'unsure' && n.value !== 'not attend') {
      a.push( {
                 'index': n,
                 'room': n.value
              }
            );
    }  // end if
    return a;
  });  //  end def arrow fn & reduce
  event.preventDefault();
});  //  end def anonymous fn & submit
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="post">
  <div>
    <label>First Name
    <input type="text" name="fname" size="25">
  </label>
  </div>
  <div>
    <label>Last Name
    <input type="text" name="lname" size="25">
  </label>
  </div>
  <div>
    <label>email address
    <input type="email" name="email" size="25">
  </label>
  </div>
  <div>
    <label>08:30 Keynote Speaker
    <select class="select" name="select 0830">
      <option value="unsure">unsure</option>
      <option value="attend">attend</option>
      <option value="not attend">not attend</option>
    </select>
  </label>
    <label>09:00 Classes
    <select class="select" name="select 0900">
      <option value="unsure">unsure</option>
      <option value="A">room A</option>
      <option value="B">room B</option>
    </select>
    </label>
    <label>10:30 Classes
    <select class="select" name="select 1030">
      <option value="unsure">unsure</option>
      <option value="A">room A</option>
      <option value="B">room B</option>
    </select>
  </label>
  </div>
  <div>
    <input type="submit" value="submit form">
  </div>
</form>
alxfyv
  • 359
  • 1
  • 5
  • 17
  • 1
    `In the snippet below, the form displays correctly, but, on submit, the console flashes an error message for a second, then disappears.` This is a symptom of the form being submitted, and replacing the page - but, running the snippet in your question, it looks like the event is `preventDefault()`ed properly, so the form does not get submitted, and the stacksnippets.net error page does not come up? – CertainPerformance Jun 27 '19 at 22:38
  • As for the null element error, see https://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element (to fix, I'd give your ` – CertainPerformance Jun 27 '19 at 22:38
  • 1
    An error in the event handler will stop JS in its tracks, and since you're only preventing default behavior at the very end, the form will still submit. Here's a fixed version: https://jsfiddle.net/khrismuc/feqzL684/ – Chris G Jun 27 '19 at 22:49
  • @ChrisG Oh, cool. I see you use `map` and `filter`. Thanks for that info. – alxfyv Jun 27 '19 at 23:42

2 Answers2

1

The console should flash for a few moments because you are not adding any url to submit the form and by default it assumes # which means that you are submitting for the same page.

The result should be something like a reload of the page.

I saw that you have White spaces the name attribute. you probably want to change that because probably some browsers will not be able to deal with them.

A J
  • 962
  • 3
  • 13
  • 30
1

In your reducer function when you don't pass an initial value to it, it will use the first element as the accumulator, so when you think you are pushing into a, that's not the case, its been replaced by your first select:

$('form').submit(function(event) {
  event.preventDefault(); // <-- MOVE this to be able to see the errors
  const SelectElms = $('select');
  // var a = [];  <-- Not needed
  var selectVals = Array.from(SelectElms).reduce((a, n) => {
    if (n.value && n.value !== 'unsure' && n.value !== 'not attend') {
      a.push({
        'index': n,
        'room': n.value
      });
    } // end if
    return a;
  }, []); //  end def arrow fn & reduce   <-- A is being initialized here, the 
                                           // second argument to reduce
console.log(selectVals);
}); //  end def anonymous fn & submit
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="post">
  <div>
    <label>First Name
    <input type="text" name="fname" size="25">
  </label>
  </div>
  <div>
    <label>Last Name
    <input type="text" name="lname" size="25">
  </label>
  </div>
  <div>
    <label>email address
    <input type="email" name="email" size="25">
  </label>
  </div>
  <div>
    <label>08:30 Keynote Speaker
    <select class="select" name="select 0830">
      <option value="unsure">unsure</option>
      <option value="attend">attend</option>
      <option value="not attend">not attend</option>
    </select>
  </label>
    <label>09:00 Classes
    <select class="select" name="select 0900">
      <option value="unsure">unsure</option>
      <option value="A">room A</option>
      <option value="B">room B</option>
    </select>
    </label>
    <label>10:30 Classes
    <select class="select" name="select 1030">
      <option value="unsure">unsure</option>
      <option value="A">room A</option>
      <option value="B">room B</option>
    </select>
  </label>
  </div>
  <div>
    <input type="submit" value="submit form">
  </div>
</form>

However, reduce runs a function that reduces all elements in the array to just one value, so you are using the wrong function. From MDN:

The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

Use map instead.

 var a = [];
 var selectVals = Array.from(SelectElms).map((n, i) => {
   if (n.value && n.value !== 'unsure' && n.value !== 'not attend') {
     a.push({
       'index': i,
       'room': n.value
     });
   } // end if
   return a;
 });
msg
  • 6,184
  • 3
  • 11
  • 26
  • Thanks for the great explanation and the solution. Why does the variable `a` not need to be initialized? Also, I know this is unfair and a burden, but have you any idea why the working fiddle (https://jsfiddle.net/alxfyv/2aj5fhwd/) code fails when I try it locally. Execution seems not to get beyond the `$('form').submit` line. I know my scripts.js file is being loaded because a `console.log` I put first is executed and the one just after the`.submit` line is not executed. I pasted the fiddle code. There is no error message. It's like asking the doctor to diagnose over the phone, I know. – alxfyv Jun 28 '19 at 00:28
  • @alxfyv It doesn't need to be initialized **only** if using reduce. You are passing an empty array as third argument. That will be filled in the function body and returned. Maybe because there is no jQuery being loaded. If I do, works for me. And remember, put your `preventDefault` first thing in the function body, otherwise if there is an exception, it won't be triggered. – msg Jun 28 '19 at 01:00
  • 1
    @alxfyv I've been saying "third argument", but it's actually the second. Sorry for the slipup. – msg Jun 28 '19 at 05:49
  • I found the error that was preventing execution locally. I added a `$(document).ready(function( ... }` to the script & everything is jake, hunky-dory, just peachy. You solved a problem that has bedeviled me for several days. I'm ever so grateful. – alxfyv Jun 28 '19 at 06:46
  • 1
    @alxfyv However, on a second read, I think the answer might be wrong. You say that the object should include "the *index position of* and the value of the `select` element". You mean the index of the `select` itself or the `option` selected? If it's the latter, then it's wrong, the index passed is that of the select. – msg Jun 28 '19 at 06:54
  • The index of the select is what I need. It corresponds to the time slot during the day in which a class will be given. Knowing the index of the select gives me the time slot which is what I really need. Your code was perfect and, to me at least, a thing of beauty. Thanks so much for continuing to think about the problem. It's quite professional. I appreciate it. – alxfyv Jun 29 '19 at 16:35