Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

2.6 Validating the Entire Form

We're finally to the point where we can validate the remaining form fields. So in this lesson, we'll write the code that automatically identifies the forms and fields we want to validate.

2.6 Validating the Entire Form

In the previous lesson, we finished generalizing our validation code so that it should be usable for just about any form control. So now we just need to validate those controls. And off screen, I went ahead and set up the name field and the message field for error reporting. So I added the span elements at the IDs and then I added the appropriate error attribute to the input element for the name and the text area for the message. Just so that we can focus on the JavaScript, because we're going to be writing a little bit of extra code in this lesson. So the first thing we need to decide is how do we want to signify that we want to validate a form? I mean, one way that we could do it is to have a function setupValidation and then pass in the form that we want to validate. I mean, in the past that's what we've done and that works. However, we also live in a day and age of unobtrusive JavaScript to where we can essentially tell our JavaScript what to do through our HTML markup. So what if inside of our form element we added a data-formval attribute? And so if a form has this attribute then that means that we are going to validate that form, if it doesn't then it means that we're going to skip that form. So let's take that idea and let's run with it. So this means that we aren't going to be retrieving the element using document.getElementById because we won't need to do that. Instead we are going to retrieve all of our forms using the querySelectorAll method. I'm gonna put this code at the bottom because I like to put my declarative code, whenever I declare variables or functions, I like to put all of that at the top. And then all of the code that's going to actually execute after that. So we are going to retrieve all of our forms using the querySelectorAll method, and our selector is going to be the form with that attribute. So there we have our selector and then we just need to iterate over this collection. Now, we can do that with a for loop, but let's also do what the cool kids do. And that is, use the forEach method for the array. Now, if you're not familiar with this method, whenever you have an array, and you want to iterate over that array without actually writing a loop, you can use the forEach method. Then you can pass in a function that is going to execute for each item in that array. And there are several things that are passed to this function, but the first thing is the item itself. And then you can write whatever code that you need to work with that item. Now you can't really change that item, but you can work with that item. Well, we can kind of do the same thing, but we can't say forms and then forEach. Now some browsers will actually let you do this, and that's fine. However, other browsers will not, and the reason why is because forms is a node list. It's not a real array, it's a node list, which is a collection from the DOM. However, we can still use the forEach method, but we have to do it like this. We're going to create an array and then we're going to call the forEach method but we're going to do so by using the the call method. Because every function has a method because a function is nothing more than a special object that will execute. So what this call method allows us to do is call a function as if it were a method on whatever object we specify. So by passing forms here, we are essentially saying call the forEach method as if it were a method on the forms, node list. And then we pass in the function that is going to execute for the forEach methods. So in this case, we're going to be working with every form and then we can set up that submit event. So let's go ahead and do that. In fact, let's just copy the code that we have up here and paste that inside of here. But, of course, we aren't going to use the form because we don't have that. We have this form that's being passed to our function, we don't need to check the validity of our field at least not yet, we will get to that here in a moment. But the main important thing is that we're iterating over our forms and for each iteration, we are setting up the submit event on each one of those forms. So as far as the submission is concerned, we've got that handled. But now we also have to set up the input event on each element within that form. Well, we can access each element with a property called elements. Every form has this elements object and it contains all of the forms controls inside of that form. So we can essentially do the same thing as we just did with the forEach. We can say forEach, we'll call it as if it were being called on the elements node this of our form. And then we will have our element and then we will set up the event listener for that element. So then we basically have this code up here, so let's copy that, let's paste that in. But, of course, we aren't using email here, we're using elements, so we will switch that. But now, we have quite a bit of nesting going on here. I don't want to take the code that we have inside of our current input event listener and paste it in because that's just more nesting. Instead, let's make this look a little prettier and we will have just a function. We'll call it validate, we'll pass in the element that we want to validate and that will take care of that. So let's go ahead and write that function, the body of which is going to be almost everything that we have inside of our input event listener. We don't need to retrieve the elements using the target because we are going to have the element as an argument. So we'll have validate(element) and then we will just paste that code in, and we're good to go there. So now we can get rid of this event listener and we're good to go, at least as far as our input validation is concerned. So if we actually test this out, we're not going to see anything whenever we submit the form because right now we're just preventing the default, we're not doing any type of validation. But if we type something into the email address, we can see that we don't have a valid email address. Until we have a valid email address and if we cleared out, then it says please enter your email. So our validation is working just not whenever we submit the form, so now we need to do that. Well, one thing that we can do is since we have this validate function. Whenever we try to submit the form, we can iterate over all of the elements, kind of like what we've done here and we can validate each one. So instead of using the forEach method, an array has an every method, this returns a boolean value. So we have every, we would pass in a function that would then work with whatever item that it needed to work with and it would return true or false based upon the function itself. So if item were equal to 1, then if every item in the array was 1, then, of course, the result of every would be true. But if there was any element in that array that wasn't equal to 1, well, then that would return false. So our code then will look like this, will have an if statement. And they we'll use the every method, we will call it using the elements object on our form. And then we will just pass in the validate function, because it already accepts the element that we want to work with, it's just going to validate that form. And if the result of every return is true, then that means that our validation passed, everything's fine so we'll just return there. Otherwise, we have a problem and we will prevent the form from being submitted. Now, that's great, except that our validate function just returns, it's not returning any values. So we have two return statements here, the first one that we can easily do is right here. If the element validity is valid, then we want to clear out the error element's message and then we will return true, that's easy to do. But up here, if we have an element that does not have an error attribute, all we are doing is returning. Well, that's not going to be good enough, because as we will see, in fact, let's just go ahead and try that. If we tried to submit we, of course, see that nope, something is wrong we need to enter a name great, okay? Now we need to enter an email address, okay? Now we need to enter our message, okay? And we click on Send Message, it's not submitting. Well, the reason is because of this statement here. If we write out to the console what that element is, we're going to see that it is our button element, because that is technically a form control. So let's fill that out, let's fill up the console, let's hit Send Message and we see that it's the button. Well, we don't really need to validate the button, do we? So here's what we can do. Let's go ahead, let's create a variable called isValid and we will check the validity of the element right here, but we're not really checking, but we're grabbing that value. So that down here we'll just use isValid. So if we don't have an error attribute, then what we can do then is just go ahead and return the validity of that element. Chances are if we don't have an error element in order to display the message, then we're not validating that element, which is the case with our button. So we'll just return isValid, that way now whenever we do this, we're going to see that it works. So let's once again, fill out all of our form fields. Let's submit it, and there we go. But just to make sure, let's try to submit the form without entering anything and we can still see that nope, our form isn't valid so it's not going to submit. So now we have a working form validation script that we can use just about anywhere. And the great thing is we can opt into it. So we just have to reference that JavaScript file and then for every form that we want to use our own validation script with. Well, we just add that data, form val attribute to the form and we're good to go.

Back to the top