DEV Community

Preston Lamb
Preston Lamb

Posted on • Originally published at prestonlamb.com on

Reactive Forms Benefits: Conditional Validation

tldr;

Reactive forms in Angular have many benefits, but one that I’ve found especially useful is the fact that I can easily add or remove validation for a given field based on the value of another field. The simplicity of doing that allows us to create complex forms in a simpler manner. Because we can subscribe to the value changes of the form as a whole or a specific field on the form, we can update the validators for any other field automatically. We’ll go over that in this post.

Form Validators

Angular’s reactive forms functionality allows you to add validators to fields on the form in the component’s class file very easily. You can read more about it in this post of mine. I’m not going to completely recap that article here, but let’s set up a demo form for this blog post. Let’s pretend that we need to capture some input from a user about their favorite foods. We’ll just be capturing their favorite dessert in this case. If they have a favorite dessert, we want them to enter it. But if they don’t, we don’t want them to enter anything. Here’s the form:

// form.component.ts

ngOnInit() {
    this.foodForm = this._formBuilder.group({
        hasFavoriteDessert: [null, Validators.required],
        favoriteDessert: ''
    })
}

In that code snippet, we created a form with two attributes: hasFavoriteDessert and favoriteDessert. The first attribute is required, the second one is not. They need to give a response for hasFavoriteDessert (possibly through a radio button group or a select element), but currently the favoriteDessert is not currently required. If we used this form as it is now, the user could submit the form without providing their favorite dessert. But if we required the favoriteDessert attribute and they didn’t have one, they’d have to provide some value for the form to be valid and that’s not what we want either. That’s where conditionally setting validation comes in to play.

Conditional Validation

AbstractControl items for Angular forms have a couple of convenient methods that we can use for adding and removing validation based on some condition. Those methods are setValidators, clearValidators and updateValueAndValidity. We’ll use these three together to accomplish our conditional validation. We’ll start by listening for changes on the hasFavoriteDessert attribute and using the previously mentioned methods to conditionally set the validators. We can do that like this:

// form.component.ts

ngOnInit() {
    // form setup

    this.foodForm.get('hasFavoriteDessert').valueChanges.pipe(
        tap((hasFavoriteDessert: boolean) => {
            if (hasFavoriteDessert) {
                this.foodForm
                  .get('favoriteDessert')
                  .setValidators(Validators.required);
            } else {
                this.foodForm
                  .get('favoriteDessert')
                  .clearValidators();
            }
            this.foodForm
              .get('favoriteDessert')
              .updateValueAndValidity();
        })
    ).subscribe()
}

Don’t forget to unsubscribe from this observable when the component is destroyed!

What we’re doing here is subscribing to the observable that emits a value every time the hasFavoriteDessert attribute value changes. We tap into the stream and use the current value from the attribute to do something. In this case, we check if it’s true and if so we set the validators for the control. It can be a single validator like I have done or it can be an array of validators. If the value is false, we clear all the validators. But the last part is very important as well. Outside the if statement we call one more method on the control, and that’s the updateValueAndValidity method. If we don’t call this, we can’t be sure that the component/form will know to require our field or let it be empty.

That’s really all you need to do! Your conditions can be more complex if needed, but the process will be the same either way.

Conclusion

Reactive forms give us a lot of flexibility in our forms and validators are one of my favorite parts of them. From being able to create custom validators (on top of all the built in validators that Angular has) to being able to conditionally add that validation to controls, reactive forms are a great option for your app.

Latest comments (0)