Can I conditionally implement validation in Angular 2 reactive form. I have this reactive form with 3 formControl fields one is a selection and the other two are input text for first name and last name. I want to conditionally implements validation for firstname and lastname based on the selection of the first field which is 'validateBy'. If the user selects 'byFirstName' only firstName should be validated. If the user selects 'byLastName' only lastName should be validated. If the user selects 'byBoth' both firstName and lastName should be validated. I created a plunker for this. Only validation byBoth 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
In a reactive form, the source of truth is the component class. Instead of adding validators through attributes in the template, you add validator functions directly to the form control model in the component class. Angular then calls these functions whenever the value of the control changes.
We can add Validators dynamically using the SetValidators or SetAsyncValidators. This method is available to FormControl, FormGroup & FormArray. There are many use cases where it is required to add/remove validators dynamically to a FormControl or FormGroup.
The problem is that your code evaluates the expression just once - when the FormGroup
is created. You need to make it dynamic by creating your custom validator that will evaluate the expression every time it gets 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);
}
}
Another way of doing it would be something like this. Seems to work on 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();
}
};
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With