Conditional Validation on Angular Reactive Form
Tags: angular, tutorial
Published: 2023-01-10 00:47:08

Have you ever needed to make a specific form field required if the value of another form field changed? In this article, learn how to make a phone number field required if the contact preference field changes its value to phone call or text message. Also, learn how to avoid losing existing validation rules that are already in place.

## Angular Reactive Form

Let’s say you have a form that looks like the following:

![Angular Form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k78ny389g9j5hznh6oyu.png)

The input for the Phone Number field has a **formControlName** of **phone**.

```html
<input formControlName="phone" id="phone" name="phone" />
```

The radio buttons for the Contact Preference field have a **formControlName** of **contactPreference**. Also, make note of the values for each radio button: email, phone, text.

```html
<input type="radio" formControlName="contactPreference" name="contactPreference" value="email" />
 
<input type="radio" formControlName="contactPreference" name="contactPreference" value="phone" />
 
<input type="radio" formControlName="contactPreference" name="contactPreference" value="text" />
```

Within your form group, the form control names should match what you used in the form itself (phone, contactPreference).

```javascript
this.form = this.formBuilder.group({
  firstName: ['', Validators.required],
  lastName: ['', Validators.required],
  email: ['', [Validators.required, Validators.email]],
  phone: '',
  contactPreference: ['email', Validators.required]
});
```

The **phone** form control has no default value or validation, meaning the user does not have to define a value for the Phone Number field on the form. The **contactPreference** form control has a default value of email and it’s a required field because it’s using the required validator. However, as you saw on the form, the user can choose from the following options for Contact Preference:

* Email
* Phone Call
* Text Message

If the user chooses Phone Call or Text Message, we want to make the Phone Number field required on the form.

## Subscribe To Value Changes

We can watch for value changes on the entire form or on a specific form control. Let’s watch the contactPreference control for value changes. Create a function called **onContactPreferenceChange** and add the following:

```javascript
private onContactPreferenceChange(): void {
  this.form.get('contactPreference').valueChanges.subscribe(value => {
    console.log(value);
  });
}
```

Add the **onContactPreferenceChange** function to the **ngOnInit** lifecycle hook. This will subscribe to value changes to the Contact Preference field as soon as the component is created.

```javascript
ngOnInit() {
  this.onContactPreferenceChange();
}
```

If you have your browser’s Developer Tools open, you’ll see that every time you select a Contact Preference, it will log the value to the console.

## Set/Clear Validators

We want to set the required validator on the phone control when the Contact Preference value changes to **phone** or **text**. If the Contact Preference value is email, we want to clear validators. Update the **onContactPreferenceChange** function to the following:

```javascript
private onContactPreferenceChange(): void {
  this.form.get('contactPreference').valueChanges.subscribe(value => {
    const phoneControl = this.form.get('phone');
    const validators = [Validators.required];
 
    if (value === 'phone' || value === 'text') {
      phoneControl.setValidators(validators);
    } else {
      phoneControl.clearValidators();
    }
 
    phoneControl.updateValueAndValidity();
  });
}
```

Now, when the user selects a Contact Preference of phone or text, we set the required validator on the phone control. If the user selects email, we clear all validators.

Because we’re updating the validators at run time, we must also call the **updateValueAndValidity** function in order for the validation changes to apply.

## Add/Remove Validators

Currently, our phone control has no existing validators on it. What if it did? For example, what if it started with a validator that checks for a phone number pattern?

```javascript
phone: ['', Validators.pattern(/PHONE_NUMBER_PATTERN/)],
```

If we use setValidators, it overwrites any existing validators. When using clearValidators, it clears ALL validators. The better option would be to use **addValidators** and **removeValidators**.

```javascript
private onContactPreferenceChange(): void {
  this.form.get('contactPreference').valueChanges.subscribe(value => {
    const phoneControl = this.form.get('phone');
    const validators = [Validators.required];
 
    if (value === 'phone' || value === 'text') {
      phoneControl.addValidators(validators);
    } else {
      phoneControl.removeValidators(validators);
    }
 
    phoneControl.updateValueAndValidity();
  });
}
```

Now, when the user selects a Contact Preference of phone or text, we add the required validator instead of overwriting existing validators on the phone control. If the user selects email, we remove just the validator that was previously added.

---
**Visit our website at [https://nightwolf.dev](https://nightwolf.dev) and follow us on [Twitter](https://twitter.com/nightwolfdev)!**