Validating form input

Hello,
I’m trying to solve an assignment that checks input from an HTML from and displays it in a sentence if complete, or else it displays an alert saying which field is missing.
Here’s my code so far:

I’m sure there’s a number of things wrong with it, but at this stage I’d like to try and get it to run, so for starters I thought I’d let the error messages be my guide.

Currently I’m getting this jQuery error:

jQuery.Deferred exception: formView is not defined ReferenceError: formView is not defined
    at HTMLDocument.<anonymous> (https://print-credentials--bennypr0fane.repl.co/js/main.js:2:16)
    at e (https://code.jquery.com/jquery-3.5.1.min.js:2:30005)
    at t (https://code.jquery.com/jquery-3.5.1.min.js:2:30307) undefined

…so apparently there’s a problem of reference. Haven’t quite grasped OOP in Javascript yet (and generally), so I’m guessing something’s off there (and probably the logic, too).
Thanks a lot for any hint!

Hello @bennypr0fane

So, yes, formView is not defined because it can’t be found.

 <script src="js/main.js"></script>
 <script src="js/formView"></script>

Looks like something is missing. Correct it and see how it goes :wink:

1 Like

Greetings,

The class formView() has been made in a separate file. You need to export this class and then, import it in: main.js.

I am still unfamiliar with the concept of importing or exporting a module and hence, can’t share the code.

One more thing: You probably need to mention type="module" in <script> of formView.js.

Regards
@snikhill

The way I understand Javascript modules, they’re built-in, but I’d need to import them explicitly if they’re not part of the standard JS distribution. However, the same does not apply for classes that I write myself (i.e. they are not modules in that sense), and they should be accessible to each other by the fact of being in the same folder (and referred to by the proper names), I think?
Is that correct?

Got it. changed it to this:

 <script src="js/formView.js"></script>

:grimacing:
Aand I’m one step closer, code is now running! Also, there’s evidence that my functions are sort of working - when I run the code using the "run"button, I get the error message that says to fill the firstName field.
However, that doesn’t happen when pressing the “send” button - it submits the form data to that form service which e-mails it to me, so I’ll investigate what the button is doing and why the script is executed at page load rather than at the click event.
Should I post subsequent problems with this code in separate threads, or put everything here?

1 Like

I’d keep it all in here, as it still concerns form validation :slight_smile:

So I guess I didn’t understand how the event handling works.
on page load, main.js is executed. This generates a formView object, and its initGUIEvents() function is called. Now that function should only do something (validateInput()) once the submit button is clicked, but apparently it sets the validateInput() in motion immediately…
EDIT: removed the form service. I actually wrote this HTML some months ago and failed to get a good hard a look at it again before starting with the JS…

also, jQuery identifier for the submit button was missing the #:

initGUIEvents() {
    $('#submit').click(this.validateInput());
  }

Now, when I load the page locally on my PC, I can’t get the error message to display: Nothing happens on page load and nothing after pressing submit

So, I just used ES6 import and export and was able to make your code run.

I even get an alert: Sie müssen noch das Feld firstName ausfüllen! on the initial run.

So, the error of the class not being defined no longer persists but still, the code is not working as you desired.

When referencing allFieldsFilled() in validateInput() method, you are not sending the arguments. [Line: 37, file: formView.js]

Also, to enable validation (using JS), you need to disable the submission of the form. [Using: preventDefault()]

well, it’s been a while… :roll_eyes:
Anyways,

I’m sending the arguments like this now:

validateInput () {
    if ( this.allFieldsFilled(this.$firstName, this.$lastName, this.$age, this.$gender) ) {
      $('#output').innerHTML = this.makeSentence(this.$firstName, this.$lastName, this.$age, this.$gender);

I added preventDefault() to the initGUIEvents():

initGUIEvents() {
    $('#submit').click( function () {
      preventDefault();
      this.$firstName = $('#firstname');
      this.$lastName = $('#lastname');
      this.$age = $('#age');
      this.$gender = $('#gender');
    });
    $('#submit').click(this.validateInput.bind());
  }

It’s just that in JS syntax, there should be an event passed into the function and referenced below:

function(event){
  event.preventDefault()

But since I’m using JQuery here, I have no idea how to translate that…
Other than that, it would appear my code still fails to generate/find/do something with a new FormView object:

TypeError: Cannot read property 'allFieldsFilled' of undefined
    at validateInput (/js/FormView.js:36:15)
    at HTMLInputElement.dispatch (https://code.jquery.com/jquery-3.5.1.min.js:2:43090)
    at HTMLInputElement.v.handle (https://code.jquery.com/jquery-3.5.1.min.js:2:41074)

Greeting @bennypr0fane

Would you mind sharing the link with your latest changes?

Also, after checking for whether all the fields are filled or not, I think, you will be returning an array(I am stating this with reference to your previous REPL link) with missed fields. Well, an array is evaluated to be true.
For example:
Try this out =>

if(['a','b']){
  console.log('true')
} else {
  console.log('false')
}
console.log(Boolean(['a','b']))

You may refer to this article for same.

Therefore, you need to change your if() condition.

Just another thought, assigning click() event to submit button doesn’t belong in FormView Class.

You should assign the same in your main.js File.

Regards
SNikhill

Thanks for your answers.
All my code is still under that first link posted above.

  1. Maybe what you wanted to say is that an empty array is thruthy?
  1. I assume you are referring to the following if-condition:
if (missingFields.length == 0) {
      return true;
    } else {
      return missingFields;
    }

Here, allFieldsFilled() doesn’t return the array unless there is something in it, so I don’t understand what you mean.
The case that I have not resolved properly yet is how to use the array of missing fileds to make a sensible sentence:

else {
      $('#output p').innerHTML = `You have to fill out ${this.allFieldsFilled(this.$firstName, this.$lastName, this.$age, this.$gender)[0]}!`;
    }

The way I understand it, this.allFieldsFilled(this.$firstName, this.$lastName, this.$age, this.$gender)[0] gets the first element of the array returned by the call to allFieldsFilled, so I should be seeing at least that one printed to the output field

I rewrote the main.js like this now:

$(document).ready (function() {
  let myForm = new FormView();
  $('#submit').click (function(){
    myForm.initGUIEvents();
    myForm.validateInput();
  })
});

initGUIEvents() is just this:

initGUIEvents() {
    this.$firstName = $('#firstname');
    this.$lastName = $('#lastname');
    this.$age = $('#age');
    this.$gender = $('#gender');
  }

Still no dice :cry:

Greetings @bennypr0fane,

Good Job! I can see that you fixed your problem. :slight_smile:

Also, I meant that you completely removed initGUIEvents() because the same doesn’t belong in the class. Also, you have already set attributes such as: $firstName, $lastName.
But still, instead of referencing these attributes, you are sending the firstName, lastName and other details as an argument to methods. It sorts goes against the point of having class. I would really like you to refer to the attributes rather sending the data as an argument.

Regards
SNikhill