What is a Directive?
Now we know how to make custom validators, which can significantly enhance user experience with more specific error messages that can pop up before submission. However, sometimes the answer that the user inputted is not quite what you are expecting, but not necessarily wrong. In these cases, you need to decide if it is better to leave the result as is, display a (hopefully descriptive) error message, or adjust the response. In this blog post, we’re going to focus on the third option, utilizing Angular directives to change the user response slightly as a gentle alert to the user that we will be saving their response in a different format than what they had originally inputted.
What exactly is a directive? Attribute directives, which is what we will be working with, are responsible for changing the appearance or behavior of a DOM element. They can be used to apply conditional styling to elements, to show or hide elements, or to dynamically change the behavior of a component according to a changing property.
How to Get Started
We’re going to pick up with the same code we left off on in the first part of this blog series, “Making More Readable Custom Validators for Angular Forms”. Let’s start with a brief reminder of what is currently being displayed to the user.
In the last blog post, we created a new page in the basic web app generated by Visual Studio for an Angular ASP.NET Core Web application called “Blog Example”. We created a reactive Angular form with two inputs for first and last name, and a submit button. Our page currently looks like so:
In the previous blog post, we focused on creating a custom validator for the first and last name sections of the form. We will keep those validators in place on those two inputs and add to this example as this tutorial moves on.
Creating a Basic Angular Directive
Before we can get into creating our custom directive, lets first set up a basic angular directive so we have a good grasp on the skeleton that is used for most directives. To do this, we’ll need to make a new typescript file. I’ve named it “ShortenNameDirective”:
Please note that your directive does not always need to be exported into a different file. Especially if you need a more secretive directive that can only be used within your module, and you want to keep it private so external modules can’t misuse it. In most cases, directives are exported for accessibility and organizational purposes, so we have exported our directive for this example.
I’ve included a few extra things in the directive to help get us started. If you are working with an Angular form, you will most likely need to be able to work with form controls, using NgControl. You can utilize an Angular life-cycle hook inside of your directive. In the case of our example, I have set up with ngAfterViewInit for us to use later. The selector name is important to include because it allows you to call your directive in a component template. Now we can move on to constructing a specific directive for our example to demonstrate how to implement your newly made directive.
Creating a Custom Angular Directive
For this example, we’ll be creating a directive to alter the inputs for our first and last name inputs. Let’s say that we decide that a name should never be longer than five characters. As we had discussed before, we could create a custom validator to display an error message to the user, but in this case, let’s say we want to change the user’s input when they click off of the input they are editing. How can we do that?
Detecting a specific action event by the user can be done with something called a host listener. In Angular, “@HostListener” listens for a particular event that you specify, and from there, you can execute some code when that event is triggered. In our case, we are using the “blur” event, which triggers when the input loses focus. I have added this new logic to the component below:
Now let’s work on creating a function that we’ll call when our event is triggered to do the action we want. In order to do that, we need to hook into the control value, check the length of the string, and if it is too long, we need to shorten it and display the shortened string to the user as a gentle reminder that only 5 character names are allowed. We can do so with the below logic:
Now, we need to hook into this directive in the angular input we are using it on. We can do so using the “shortenNameDirective” inside of the input tag section for the input we are using it on.
And don’t forget to add the new file to your app.module.ts (or if you have multiple modules, make sure to add the file to the corresponding modules where the directive is being implemented):
After doing so, you’ll be able to see the effects of your directive on your Angular form. To prevent any weird behavior when the page view is initialized, I call the function we just created in the ngAfterViewInit in the page’s component:
After everything is set up, you should see the directive affecting your Angular form the way you expect. For example, if we write a name longer than five characters in the first name input, it should shorten it as you click off the input.
In the real world, our directive wouldn’t have much use since names are normally longer than five characters. However, there are still many cases when this type of text manipulation in forms is better than a simple validator, such as formatting amounts to have two decimal places when dealing with money. Having a large arsenal of ways to manipulate inputs and show errors allows developers to more gently push users to provide more correct inputs without making the process annoying or unintuitive while still having more handleable form responses.