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.
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.
Share Improve this question asked Jul 17, 2017 at 6:43 Cengkuru MichaelCengkuru Michael 4,8101 gold badge36 silver badges34 bronze badges 04 Answers
Reset to default 4Here is how you can dynamically add or remove validator to some control
private addValidator(control, validator) {
let existingValidators = control.validator;
control.setValidators(Validators.pose([existingValidators, validator]));
control.updateValueAndValidity();
}
And to Remove validator
private removeRequiredValidator(control, otherValidators) {
control.clearValidators();
if (otherValidators) {
control.setValidators(otherValidators);
}
control.updateValueAndValidity();
}
Both the use of custom validators and setValidators
can get very plex 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.
Make use of setValidators
to set/unset validators for form controls
import {FormControl, Validators, FormGroup} from "@angular/forms";
onRefNoEntered() {
if(this.contractsFilter.controls['refNo'].value && this.contractsFilter.controls['refNo'].valid) {
this.contractsFilter.controls['selectedContractType'].setValidators(null);
this.contractsFilter.controls['selectedYear'].setValidators(null);
this.contractsFilter.controls['selectedPde'].setValidators(null);
}
else {
this.contractsFilter.controls['selectedContractType'].setValidators(Validators.required);
this.contractsFilter.controls['selectedYear'].setValidators(Validators.required);
this.contractsFilter.controls['selectedPde'].setValidators(Validators.required);
}
}
I faced a similar issue and, inspired by this solution, made something like this:
const control = new FormControl(null,
[this.conditionalValidator(Validators.required)],
[this.conditionalAsyncValidator(this.validatorService.customAsyncValidator(params))] );
private conditionalValidator(validator: ValidatorFn): ValidatorFn {
return (control: AbstractControl): ValidationErrors => {
if(this.condition) {
return null;
}
return validator(control);
}
}
private conditionalAsyncValidator(validator: AsyncValidatorFn): AsyncValidatorFn {
return (control: AbstractControl): Observable<ValidationErrors> | Promise<ValidationErrors> => {
if(this.condition2) {
return observableOf(null);
}
return validator(control);
}
}