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)],
});
source to share
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);
}
}
source to share
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();
}
};
)
}
source to share
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')
}
source to share