Making More Readable Custom Validators for Angular Forms
What are Angular Forms?
Angular has become a powerful tool in application development over the years. Companies in every field utilize this framework to create powerful websites that provide a clear and fast user experience. In many cases, there is a need to collect information from the user, for everything from gauging user experience to collecting vital documents and information when a claim is being filed. Angular has two different types of forms that are optimized for effective data collection from the user. Template-driven forms are asynchronous in nature and known for having most of their logic driven by the template. Reactive driven forms are known for being mostly synchronous and having logic that primarily resides in the component. In this blog, we will be tackling reactive forms, and more specifically, how to make your life easier with more readable validators.
How to Get Started
Lets first start with a basic ASP.NET Core Angular Web Application. I created this example using Visual Studio 2017, .NET Core 2.1, and Angular 5. When the starter app is first run, it looks like so:
I will be displaying the forms I am discussing in this blog on a new page I have made in the app under the tab “Blog Example”.
How to Construct a Reactive Form
Lets first understand how to set up a standard reactive form. In most cases, when collecting user data, you will want them to identify themselves somehow. In this case, let’s have the user enter in their first and last name into our reactive form. We need to provide two basic form inputs so the user can enter what we want, like so:
I first setup these forms by creating the form group in the component with the below code:
Here, I am using “FormBuilder” to create a form group on the initialization of this component. As you can see, there are no validators added to the controls in this form group yet. The form is now created and ready to be displayed on the template. I displayed the form to the user with the below template code:
In this template, you can see that the name that you use when initializing the form group and the form controls matters, as you use those names to hook into the correct form group and controls within the template. Now, we can enter our first and last name, but there is no validation to stop us from submitting with an incorrect input. Let’s fix that with a basic validator.
How to Add a Basic Validator
Now, let’s add a basic validator to our form inputs to alert the user something is wrong when they try to submit. For this example, I will be using an Angular built-in validator that simplifies checks if something is entered in the input. With the below changes to the component and the template, this can be achieved:
(Please note: At this point, I have changed the form to be in column format as a quick fix to prevent switching from column to row format for the example)
This validator checks to see if you have provided an input of any combination of characters. If you try to submit without inputting anything into either the first name or the last name spot, it will give an error and not submit. It will also show an error of “Required” under the inputs that were missed. Here is what will be displayed to the user if they press “Submit” without filling out either input:
If both inputs are filled out, the form will show as submitted
How to Create a Custom Validator the Normal way
Now we’re getting some form of validation, which is good, but we realize that numbers do not belong in names and should not be allowed as input. The method I’m calling the “Normal” way in this section refers to the traditional Angular documentation way of creating a custom validator by executing a function that returns your validator function. Let’s use this standard method to limit input to just letters:
The custom validator is made in the component, and the proper error messages are shown only when there is an error using “ngIf” to show and hide messages. Now the messages are more accurately checking the inputs for validity:
When I was first starting to learn how to make custom validators, I found the syntax for a custom validator to be very different from how the rest of my functions were structured. Can we structure our custom validators to fit the same structure as the rest of our functions?
How to Create a Custom Validator the More Intuitive Way
Until now, we have been creating custom validators where a function is executed that returns your validator function. Instead of doing this, we can instead pass a pointer to your validation function, which can be much more readable to collaborators in the same code base who are less well-versed in Angular forms. Let’s try to reconstruct our validator so that it is in a format we see more often and is more readable:
In this new format, the structure of the function is more conventional to how a normal function is, and therefore is more readable to other developers, especially if they haven’t worked with custom validators before. In order to use this method of validation, the function needs to be passed into the control without the parenthesis.
And that’s it! That’s how you make a custom validator in a format that is easier to read for other developers and more standard with the format of the rest of the form.