Conditionally perform validation on form fields of Angular 2 reactive form

Can I conditionally implement validation in Angular 2 reactive form. I have this reactive form with 3 formControl fields, one of which is the selection and the other two are introductory text for the first and last name. I want to conditionally implement validation for first name and last name based on the selection of the first field called "validateBy". If the user chooses "byFirstName", only firstName needs to be checked. If the user selects "byLastName", only the lastName needs to be checked. If the user selects "byBoth", both firstName and lastName must be checked. I created a plunger for this. Only check for both criteria works.

ngOnInit() {
this.myForm = this._fb.group({
  validateBy: ['byFirstName'],
  firstName:  ['', isFirstNameValid(() => (this.validateBy === 'byFirstName' || this.validateBy === 'byBoth'),
                     Validators.required)],
  lastName: ['', isLastNameValid(() => (this.validateBy === 'byLastName' || this.validateBy === 'byBoth'),
                     Validators.required)],
}); 

      

https://plnkr.co/edit/X0zOGf?p=preview

+5


source to share


3 answers


The problem is that your code evaluates the expression only once - on creation FormGroup

. You have to make it dynamic by creating your own validator that will evaluate the expression every time it is called:



this.personForm= this.fb.group({
  firstName: ['', Validators.required];
  lastName:  [
    '', 
    conditionalValidator(
      (() => this.isValidationForLastName === true),
      Validators.required
    )
  ]
});

function conditionalValidator(condition: (() => boolean), validator: ValidatorFn): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} => {
    if (! condition()) {
      return null;
    }
    return validator(control);
  }
}

      

+6


source


Another way to do it would be something like this. Seems to work for the plunker



  ngOnInit() {
    this.myForm = this._fb.group({
      validateBy: ['byFirstName'],
      firstName:  [''],
      lastName: [''],
    });

    this.myForm.get('validateBy').valueChanges.subscribe(
        (validateBy : string) => {
          if (validateBy === 'byFirstName' || validateBy === 'byBoth') {
            this.myForm.get('firstName').setValidators([Validators.required]);
            this.myForm.get('firstName').updateValueAndValidity();
          }
          if (validateBy === 'byLastName' || validateBy == 'byBoth') {
            this.myForm.get('lastName').setValidators([Validators.required]);
            this.myForm.get('lastName').updateValueAndValidity();
          }

        };
      )
  }

      

+6


source


I made a library just for this.

Your solution might look something like this:

constructor(private cv: ConditionallyValidateService, private fb: FormBuilder) {}

ngOnInit() {
    this.myForm = this._fb.group({
        validateBy: ['byFirstName'],
        firstName:  [''],
        lastName: [''],
     });

    cv.validate(this.form, 'firstName')
        .using(Validators.required)
        .when('validateBy')
        .is('byFirstName')

    cv.validate(this.form, 'lastName')
        .using(Validators.required)
        .when('validateBy')
        .is('byLastName')

    cv.validate(this.form, 'firstName', 'lastName')
        .using(Validators.required)
        .when('validateBy')
        .is('byBoth')

}

      

0


source







All Articles