4.2 Form Validation
As you’ll see in this lesson, it’s not difficult at all to add validation to our form controls.
1.Introduction5 lessons, 29:28
2.The Projects List6 lessons, 39:35
3.The Users5 lessons, 31:28
4.The New Project Form4 lessons, 30:48
5.The Project Page4 lessons, 49:46
6.Conclusion2 lessons, 04:08
4.2 Form Validation
In our previous lesson, we created our new project form where the user will eventually be able to create new projects. Now we want to add a little bit of validation to our system. Specifically, we want to add some validation for our name field here. Now we're going to keep it pretty simple. We just want to make our name field required. So let's look at how we might be able to do that. First of all, we're going to need to import the validators object from the angular/forms package. So after FormGroup here, I'll go ahead and add the validators. There are several different validators that you can use, and the one we're interested in here is validators.required. Now, the way to add validations to a field is right within our fb.group function here. Where we create our FormGroup, we can go ahead and include validators. So we want to add some validators to this name field. So, right now this field is just an empty string. Let's change this instead to be an array. And the initial value for this field will be the first item in the array, so we'll put that as a string. And then the validator is the second property of this array. Now, if we wanted to use just a single validator, we could just add it like this. So we'll say, Validators, which is our class name here, and then ., and then we have a bunch of properties or methods which are the Validator names. So for example, we want to use required. So this would be a great way to use just a single Validator. In this way, the name field will be required and our form will be considered invalid if this name field is not given a value. However, I'm gonna comment that out and instead of just including one Validator we want to use two Validators. So the way we do this is by doing Validators.compose, and we pass compose an array of Validators. And so we can use multiple Validators to validate our name field. So, for example, we can say both Validators.required. And we can also say Validators.minLength, and of course minLength is a function so let's say this has to have at least 3 characters in the name. So, this way our name is now gonna be validated against these two different validators. Now, how are we gonna go ahead and show this validation in our form? First of all, I'm going to import another class from angular/forms, and this one is AbstractControl which is a parent class of the form control and then let's add a name property here which is going to be an AbstractControl. And then let's pull that name out of the form. Let's get a reference to the name inside of our FormGroup. So we'll say, this.name = this.form.controls and we'll get the name by square bracket. You of course could just do controls.name but two things here. First of all, most of the documentation will show you this. So it's kind of the convention and then also if we use controls.name, the typescript compiler seems to complain. So it's really up to you on this front, both methods will work. Okay, so now we can use this name property from within our template. In fact, on our md input element here where we have our name input, we could replace form.controls square bracket name with just name because it references the same object now. However, I'm just gonna leave it uniform. But what we will do here is add a little bit of validation. But before we get to that, let's talk about our handler method here. Now that we have these Validators on one of the controls within our form, we can ask the form itself if it is valid. So for example, here we could say if (this.form.valid). Well, then we can go ahead and console.log. Otherwise, let's add another property to our class, we'll say this.submitted = true. And I'll show you how we're gonna do this in a second. But let's just add it to the top here. We'll say submitted and it's going to be a boolean of course that will default to false. Let's see if our form is valid. What we can do is if we save this and we come back to our form here, if I go ahead and click Save, you can see that nothing is being printed in the console. If I type in a name here with just two letters and click Save, nothing. But as soon as we hit three letters, you can see that now our object is being printed out. And of course this makes sense because our form is not considered valid until the name field has at least 3 characters in its name. But of course, this doesn't exactly work for us because the user won't know why the form is not submitting here. So what we want to do is tell the user what the problem with the form is when they try and submit it. Now there are a couple of ways we can do this. Let's add a paragraph here with a class='error'. And in this we can include the text, Name field is required, for now. Now of course, if we just do this like that and we come back to our form here, we have this error and it doesn't matter if we fill in the name or not, the error is always gonna show up. So what we want to do is add an ngIf to our paragraph and only show this if that field has not been filled. So we can say name.valid. Valid is, of course, a property on our form control name, and so we can say, if this element is not valid, then go ahead and show the error. So if we come back, you can see that we have this for starters, but as soon as I type in enough of a name, it disappears. And that's pretty good. However, the problem here is that maybe we don't want this to show initially. We want them to have a chance to type it in before they actually see the error. So what we can do is use our submitted property that we created. And we can only show this if submitted is true and the name is invalid. So if we come back to our browser now and this refreshes, you can see we don't see anything, but if I go ahead and click Save, then our error message appears because they haven't typed anything in. And if I type it in, once it is valid, it will disappear and you can see we get this to the console. So that's one way to do this, however, notice that we're just saying, is the name valid?. We're not referencing the specific validations that we have used. So instead of just using the control's valid property, we can use the hasError property. hasError takes a string as its property and that string is usually the name of the validator that we used. So for example, we can say submitted has error required, so and of course now we want to take off our reversing exclamation point there. So if the form has been submitted and the name has the required error, then go ahead and display this. So let's see, we have this again, I click our Save button, the error appears. I type it in, the input element no longer has the error and so the error message disappears. Okay, now there is another case that we might want to be prepared for. If I refresh this page, what happens if I type in a name but then I remove the name? Maybe then we do want the error to appear. So the way we can manage that is by using the dirty property. The dirty property on a form control set to true if its value has been changed. So we can put submit and dirty in parentheses. We'll say, if this has been submitted or name.dirty, and we have the required error then show our error message here. So this time as you can see, if I type in the name but then I delete it, we have our error showing up. Excellent, that's pretty good. Let's go ahead and copy this, paste it underneath and instead of using the required error, let's change this to be the minlength error and we will say, name field must be longer than 2 characters. So now, when we come to the form we have no errors and I can start typing the Name and notice that as soon as I start typing the field is considered dirty because I made a change to its value. But it's also less than the necessary three characters. And so we immediately see the name field must be longer than two characters. I can go ahead and finish typing my word, and you can see that the error has disappear. Or if I go ahead and delete the characters, you can see that this is showing up. All right, so now that we have our validation working, there's another field that we want to add to this form and we'll look at that in the next lesson.