Become a member
to unlock all features

Level Up!

Access all courses & lessons on egghead today and lock-in your price for life.


    Implement a custom form validator with Angular Formly


    Formly comes with a lot of built-in validators. Nevertheless you most likely will have to to implement some custom validation. In this lesson we're going to do exactly that. Learn how to create a custom validator with Formly.



    Become a Member to view code

    You must be a Pro Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson
    orLog In




    Instructor: 0:00 As we have seen, Formly has some built-in validators such as the required validator here or the min validation. This works quite well in many cases, but then there are some custom cases, some specific ones which you might encounter in your enterprise application, where you definitely need a custom validator to be built.

    0:18 Formly obviously supports that as well. Let's see how that works. We actually have different kind of ways on how to hook up a custom validation. I couldn't come up really with a good example. Let's assume here we have a field that contains an IP address.

    0:34 We definitely want to add that here to our form as well. Let me just go to the very end. Let me create here a new configuration which is here for a field IP. It will be a normal input field. In the template options, we just specify the label for now, IP address.

    0:53 First of all, let's define the validation of such an IP address. Here, I define a function, for now directly in our component here. I call it IpValidator.

    1:05 That validation function here gets the control, which is a formControl from Angular reactive forms. As a result, what it returns is validation error. These are all classes directly coming from the Angular core packages. We are not too much interested on how to implement the actual validation. Let me just paste in a validation for such an IP address.

    1:27 I already can see here I first of all return when the control doesn't have a value. We want to validate only if we have actual value. The validation of an empty field is the responsibility of a required validator.

    1:39 With that, that validator itself is already made. We can go down to our field again. First of all, we want to definitely have here a required validator as well, such that the user has to input some field.

    1:52 Then let's also add the validators. We can directly do that here by using the validators property. This takes an object. Then we have a validation array, where we can actually then reference our function. Here we give it our IpValidator.

    2:09 Now let's go here. Let's try some number. You can see it gets read. Let's try some valid IP. The field is valid again. Obviously, we also have to define a message. As we know, we can define a message directly here in our app module, for instance.

    2:26 Let's create here a custom message. We get error. We get the field. Here, let's return field.formControl. We could directly go through the formControl value. To get the current value of our formControl, it's not a valid IP address. Of course, we have to register that as well down here so we have here the name IP and message would be our IP validation message.

    2:52 Again, if I enter here some value like this, you can see one to three is not the next valid IP address. This is one way of implementing our validator by directly implementing it here in our component class and then referencing it directly on our field here below on our validator's property.

    3:10 Another approach we could take is to make this a global validator. Since IP validation is quite a generic function, we could actually extract this here, move it to a dedicated validation messages for our validator's file, but right now let's just place it here on top of our app module. We implement here the validator, let it import here to missing Angular classes and then we register it here as validator on our form module.

    3:38 We can just create here the validator's property which is very similar to what we did on our form refill configuration and this is an array. It takes an object where we give it the name of the validator and actual validation function which will be IP validator.

    3:53 With that we have to find our validator. Now we can go back to our app component and to our form refilled here. Rather than specifying it directly in this way, we can just provide here the string IP which is the name of the validator which we just defined.

    4:09 As you can see, if I now type in some characters, we again get the normal validation which we expect from our validator. Now it is defined as a global validator and can be reused on multiple forms within our app.

    4:20 Another way of defining validators is by directly using so-called expressions. Instead of you referencing our data which we have to find globally, we could provide just some ad hoc validation for a specific use case in our form.

    4:33 Here, I could give it a property called IP. Let's call it IP2 just to make sure we don't collapse with the one we already defined. Here, we'll have the possibility to provide an expression which gives me here a custom form control and a plus directed expression to validate that which is the exact as the one we used before.

    4:53 Also, I can directly provide here the message. That would give me the hour and it will also give me the form refill config just as we have seen in the outer case before. Then I can provide here a message and say, "Field.formcontrol of value." Just as we did before an example is not valid. Again, this works exactly as we would expect.

    5:19 Now we can see here this message a little bit different than the one we defined before and our validation that makes sure that we actually using this one here inline in our form.

    5:27 This is very powerful if you have a very simple validation just for a specific field in one of your forms. You can directly hook them up related to that field. You don't have to define them globally in a different file.