Angular: How to implement conditional custom validation
suppose we have a form to fill some personal family details: name, birth date, partner details and children details.
And we want the child name to be required, but only if user has children, when doesn’t check the checkbox:
I do not have any children
Also we want the child birth date to be required, only if the child name was filled in.
so, I write a custom validation
requiredIf that get
boolean input, if the input is true, then control must have value.
that is a very simple validator:
and here is my form:
but, with this implementation, if I will check and uncheck the “no children” checkbox without touching the control, the validation status won’t be changed.
here is the broken behavior:
The child name control remains invalid, also if I checked the “no children” checkbox, angular doesn’t know on the need to re-validate.
same for child birth date, because initially the name was empty, then birth date remain valid, even if I fill the name. and I expect birth date to be invalid now.
control validation status is changed only if the control value is changed, not if the validation input is changed.
so, what will be the hack?
let’s see the
What is the purpose of the second method?
This method is endpoint for angular to register validation changed function to the validator implementation, and validator can call it when it wants to raise validation changed, for example if the validation input is changed.
let’s implement this in our validator:
Now, when there is a change in the directive input
requireIf, then we call the
this._onChange() that angular registered us. now angular knows that it need re-validate and status is being changed.
now it will work, follow the red border color that indicates invalid field, and see that it becomes invalid and valid also when I don’t touch this.
check angular built in validation. and find that they implement them as described above. for example maxLength:
So far so good, but how will it work in reactive form? when I don’t have even a directive, just
The issue here that validationFn, which I use to built the form control, must return a function, that can get only form control, means no input, input can be defined in the closure, but can’t be changed…
unless it’s mutable object input..
let’s make it mutable input:
now if I change the
requiredIf value, the validation method can work with the refreshed value, but still it won’t be revoked, only when I touch the control itself, here, in reactive forms, I can’t do the hack described above, because I didn’t use directive at all.
The way I found to do it is to register input changes, and call
control.updateValueandValidity() which revoke the validation cycle.
Here is an issue I opened in github that describe this problem.
here is same code in reactive form, very complex, I hope above issue will be solved and it will be easier.