Angular: How to implement conditional custom validation

Brachi Packter
Frontend Weekly
Published in
3 min readDec 28, 2017

Suppose we have a form to fill some personal family details: name, birth date, partner details, and children details.

like this:

And we want the child name to be required, but only if the user has children when he/she doesn’t have children, then he/she should 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 gets boolean input, if the input is true, then the 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 again 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 childbirth date, because initially, the name was empty, then the birth date was valid, even if I fill the name. and I expect the 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.

What will be the hack?

let’s see the validator interface:

What is the purpose of the second method?

This method is an 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:

When there is a change in the directive input requireIf, then we call the this._onChange() that angular registered us. and then angular knows that it needs 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.

see full code example

Check angular built invalidation. and find that they implement them as described above. for example maxLength:

Reactive form

So far so good, but how will it work in reactive form? when I don’t have even a directive, just validatorFn:

The issue here that validationFn, which I use to build the form control, must return a function, that can get only form control, means no input, the input can be defined in the closure, but can’t be changed…

Unless it’s mutable object input…

Let’s make it mutable input:

Here, 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, 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.

See is an issue I opened in Github that describe this problem.

Also, here is the same code in the reactive form, very complex, I hope the above issue will be solved and it will be easier.

--

--