Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional validation in Angular 2

Validation in Angular 2 is pretty straight forward which is awesome. However, how would one go about making a required field optional if some other field is selected.

Here are my rules

this.contractsFilter = this.fb.group({
  selectedContractType: ['', [Validators.required]],
  selectedYear: ['', [Validators.required]],
  selectedPde: ['', [Validators.required]],
  refNo: ['', []]
});

I want other fields flagged as required to be 'un-required' if the refNo is provided by the user.

like image 367
Cengkuru Michael Avatar asked Jul 17 '17 06:07

Cengkuru Michael


2 Answers

Here is how you can dynamically add or remove validator to some control

private addValidator(control, validator) {
    let existingValidators = control.validator;
    control.setValidators(Validators.compose([existingValidators, validator]));
    control.updateValueAndValidity();
  }

And to Remove validator

  private removeRequiredValidator(control, otherValidators) {
    control.clearValidators();
    if (otherValidators) {
      control.setValidators(otherValidators);
    }
    control.updateValueAndValidity();
  }
like image 93
umar Avatar answered Sep 30 '22 10:09

umar


Both the use of custom validators and setValidators can get very complex very quickly. I prefer to configure the validators as they may be required and then conditionally enable or disable them.

Using exactly your code:

this.contractsFilter = this.fb.group({
  selectedContractType: ['', [Validators.required]],
  selectedYear: ['', [Validators.required]],
  selectedPde: ['', [Validators.required]],
  refNo: ['', []]
});

I would then subscribe to valueChanges for refNo:

this.contractsFilter.controls['refNo'].valueChanges.subscribe(value => {
  if (value) { // There is a refNo specified
    this.contractsFilter.controls['selectedContractType'].disable();
    this.contractsFilter.controls['selectedYear'].disable();
    this.contractsFilter.controls['selectedPde'].disable();
  } else {
    this.contractsFilter.controls['selectedContractType'].enable();
    this.contractsFilter.controls['selectedYear'].enable();
    this.contractsFilter.controls['selectedPde'].enable();
  }
});

Now your validators are all specified in one consistent place, and you can still control whether the validators are executed or not.

like image 32
Cobus Kruger Avatar answered Sep 30 '22 08:09

Cobus Kruger