1/12/2019 UPDATE: I expanded on this idea quite a bit and built a ready to use library that you can download from the NPM. If you just want a control to use, download the library and give a try. The original article follows below.
At some point you will need to display validation messages in your app. The Angular docs site has a useful section on form validation but it centers around hand-coding each validation message. We want to automate that process and display our messages in a standard way.
Consider the following simple example component with a form:
The supporting module looks like this:
I also added some simple CSS to beautify the form a bit but I am omitting it for brevity. At this point, our app looks like this:
Validation Summary Control
Next we will build a validation summary to support the validations we are using so far (required and minlength). Let’s create a new control called validation-summary. In order for our control to have access to the form, we will pass it our form template variable (which we captured with <form id="mainForm" #userForm="ngForm" (ngSubmit)="createUser()">). My validation-summary module looks like this:
The first thing you might notice about this code is that I am throwing an error on init if the form property is not set to an instance of type NgForm. Why? Because I am trying to ensure that future developers have useful information in their consoles. Here’s what happens if you try to use this control and don’t set the form property:
This is more useful than failing silently or throwing a generic error.
We are subscribing to an observable called statusChanges. Via the angular docs you can see this observable emits an event every time the validation status of the control is re-calculated - which is exactly what we want. Next, we are iterating over the keys (which are based on the name attributes in our form) of our controls to search for errors. The signature for the controls member looks like this:
It’s worth noting that the minlength error object also exposes a property called minlength.requiredLength which you could use in your validation summary if you want to. You can use developer tools to snoop around the validation objects to learn more:
I have created a simple template to display the errors in my validation summary module:
And finally I added the validation summary to the main form with the following tag:
When put together, it looks like this:
What About Custom Asynchronous Validators?
Let’s implement a custom asynchronous validator and then extend our validation summary to handle it. Here’s my new validator to make sure things aren’t “bad”:
As you can see, we are returning a ValidationErrors object with a message property. I’m delaying the response by 500ms to simulate a server response delay. Now all we need to do is check for that in our validation-summary module by adding the following to our generateErrorMessages function:
I’ll add my new validator to the password field:
If I enter a password > 8 characters long with the string “bad”, you can see this custom validation in action:
That’s it. We have a flexible, custom starting point for a validation summary that you can edit/customize to your liking. It works with built-in validators as well as custom, async validators. You can try it it yourself on stackblitz and edit it to your liking.