Issue
The conditional validator has probably been asked a lot. But what I could never find is when this validator is to be invoked.
Suppose I have a form with only two fields
this.form = formBuilder.group({
emailRequired: [false],
emailRecipients: ['']
});
I now want the field emailRecipients
to have a required validator ONLY when the emailRequired
field is set to true
. I came up with this
const emailRecipientsControl = fb.control('', {
validators: [
(x) =>
{
// When emailRequired is set to true, the email control is required.
if (x.parent?.get('emailRequired').value)
{
return { required: true }
};
return null;
}
]
});
this.form = this.fb.group({
emailRequired: [false],
emailRecipients: emailRecipientsControl
});
This actually somewhat works, but the problem is that my custom validator is only invoked when the emailRecipients
value has been changed, whereas I need it to be invoked when BOTH emailRecipients
or emailRequired
have been changed.
So to summarize: how do I define WHEN to invoke (custom) control validation?
Note: my real form is a lot larger then this example and I'd rather not subscribe to the entire form.
Solution
As you say, Angular not "validate automatically" an input if you don't use setValue or change the input. So the simpler solution is force this validation when you change the checkbox
<input type="check" formControlName="emailRequired"
(input)="form.controls.emailRecipients.updateValueAndValidity()">
Update Based in recomendation from @MoxxiManagarm. Would be better if we can defined our formGroup and don't need take account when we need subscribe to valueChanges or use (input).
We can define a "validator" like
export function checkControl(controlName:string)
{
return (x:AbstractControl) =>
{
const control=x?.parent?.get(controlName);
if (control)
control.updateValueAndValidity()
return null;
}
}
This allow us write
form = new FormGroup({
emailRequired: new FormControl(false,checkControl('emailRecipients')),
emailRecipients: new FormControl('',requireIf('emailRequired'))
});
Then we simple
<form [formGroup]="form">
<input type="checkbox" formControlName="emailRequired">
<input formControlName="emailRecipients">
{{form.get('emailRecipients')?.errors|json}}
</form>
NOTE: the validator "requiredIf" like
export function requireIf(controlName:string)
{
return (x:AbstractControl) =>
{
if (x?.parent?.get(controlName)?.value && !x.value)
{
return { required: true }
};
return null;
}
}
See that, when we change the "checkbox", the formControl form.controls.emailRecipiens
are updateAndValidity.
Well, this "validators" makes more "robust" the typical repeat password validators problem.
export function equalsTo(controlName:string)
{
return (x:AbstractControl) =>
{
const control=x?.parent?.get(controlName);
if (control && control.value && control.value!=x.value)
{
return { notMatch: true }
};
return null;
}
}
The form
form2=new FormGroup({
password:new FormControl('',checkControl('repeatPassword')),
repeatPassword:new FormControl('',equalsTo('password'))
})
Answered By - Eliseo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.