Home > Software design >  angular reactive form conditionally validate fields based on another field's value
angular reactive form conditionally validate fields based on another field's value

Time:10-07

This is my code

detailsGroup = new FormGroup({
    userId:new FormControl('1'),
    firstName: new FormControl('', Validators.required),
    lastName: new FormControl('', Validators.required),
    email: new FormControl('',[ Validators.required, Validators.email]),
  });

I want if the userId equal to 1 then the firstname last name and email does not required otherwise those 3 fields change to required and the email also validate the email adress.

Thanks

CodePudding user response:

In order to achieve this you can use the setValidators and clearValidtors methods available with the FormControl class. Below is how you can use them to dynamically add or remove validators from a particular control of the form. Also the setValidators method takes either a single validator or an array of validators as parameters, so in case of email you can use it like this

this.detailsForm.get('email').setValidators([Validators.required,Validators.email]);

Since angular provides both the required and the email validators, you won't have to write any custom validator functions.

import { Component, OnInit, VERSION } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  name = 'Angular '   VERSION.major;
  detailsForm: FormGroup;
  validation: boolean;
  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
    this.detailsForm = this.formBuilder.group({
      userId: ['', [Validators.required]],
      firstName: ['', [Validators.required]],
      lastName: ['', [Validators.required]],
      email: ['', [Validators.required]],
    });
    this.detailsForm.get('userId').valueChanges.subscribe(() => {
      const val = this.detailsForm.getRawValue();
      if (val.userId.toString() === '1') {
        Object.keys(this.detailsForm.controls).forEach((controlName) => {
          this.detailsForm.controls[controlName].clearValidators();
          this.detailsForm.controls[controlName].updateValueAndValidity();
        });
      } else {
        Object.keys(this.detailsForm.controls).forEach((controlName) => {
          this.detailsForm.controls[controlName].setValidators(
            Validators.required
          );
          this.detailsForm.controls[controlName].updateValueAndValidity();
        });
      }
      this.validation = this.detailsForm.get('email').valid;
    });
  }
}

Here is a working demo of the same. If you type 1 email has no validators and is found valid. If you type any other value the email control becomes invalid.

You can play with the above editable code here

CodePudding user response:

You should write a custom validator, something like this: Demo: https://angular-custom-validator-p2u1jv.stackblitz.io

function nameValidator(form: FormGroup): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const needRequire = form.get('userId').value != 1
    const noValue = needRequire ? !(control.value) : false
    return noValue ? {required: control.value} : null;
  };
}
this.form = new FormGroup({
  userId:new FormControl('1'),
  firstName: new FormControl(''),
  lastName: new FormControl(''),
  email: new FormControl('',[ Validators.required, Validators.email]),
});

this.form.get('firstName').setValidators(nameValidator(this.form))
this.form.get('lastName').setValidators(nameValidator(this.form))
  • Related