I am trying to figure out the best way to implement cross field validation in Angular.
For example, I have a select field that makes another field mandatory.
I want to be able to:
So far, I came up with three solutions but they don't feel so convincing to me.
Here is a Stackblitz implementation that demos my investigations.
UPDATE - ANOTHER APPROACH See this SO
UPDATE - A BETTER APPROACH
Create the customValidator
over the form and use the validator to use setError
to the control required. Using setError
, make that Angular adds ng-invalid
for us, ad we needn't subscribe to value change. See:
form: FormGroup = new FormGroup(
{
input1: new FormControl('optional'),
input2: new FormControl(null),
},
{ validators: this.customValidatorForm() },
);
customValidatorForm() {
return (form: FormGroup) => {
const error =
form.get('input1').value != 'optional' && !form.get('input2').value
? { required: true }
: null;
form.get('input2').setErrors(error); //<--see the setErrors
return error;
};
}
See stackblitz
OLD ANSWER
Just use a customValidator
like:
form: FormGroup = new FormGroup({
input1: new FormControl('optional'),
input2: new FormControl(null, this.customValidator()),
});
customValidator() {
return (control: any) => {
if (!control.parent) return null;
let mandatory = control.parent.get('input1').value;
return mandatory != 'optional' && !control.value ? { required: true } : null;
};
}
Another option for not ask for control.parent
it's use .bind(this)
. This allow us have inside the validator to all the variables of our component, and of course access to this.form
:
form: FormGroup = new FormGroup({
input1: new FormControl('optional'),
input2: new FormControl(null, this.customValidator().bind(this)), //<--bind(this)
});
customValidatorBind() {
return (control: any) => {
if (!this.form) return null;
let mandatory = this.form.get('input1').value;
return mandatory != 'optional' && !control.value ? { required: true } : null;
};
}
Well, as we want that when change input1
input2
was checked, you need use, after create the form subscribe to valueChanges
:
this.form.get('input1').valueChanges.subscribe(() => {
this.form.get('input2').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