14

Is there any way to do conditional validation in AngularJS? The problem I am trying to solve is basically a list of radio buttons that enable/disable inputs based on the selection. The following image portrays the problem. The first text input accepts only letters, the second one accepts only numbers. Both have ng-pattern and ng-required set. (The working example on Plunker)

Screenshot of the problem in question

What I would like to achieve is that when the radio button is selected, the validation turns off for the corresponding input field.

I had hoped that setting the ng-disabled to true would prevent the invalid state from being set for the form controls in question, but alas, that is not the case.

The only solution I have found so far is to clear the input whenever selecting another choice and setting the ng-required to false. Is there any sensible way of achieving this or is the only solution to take the elements out of DOM entirely?

1
  • That this wasn't implemented with first class support in AngularJS was a big oversight for real world form validation. Commented Apr 26, 2021 at 13:38

3 Answers 3

7

Try this directive:

.directive('disableChildren', function() {
  return {
    require: '^form',
    restrict: 'A',
    link: function(scope, element, attrs,form) {
      var control;

      scope.$watch(function() {
        return scope.$eval(attrs.disableChildren);
      }, function(value) {
        if (!control) {
          control = form[element.find("input").attr("name")];
        }
        if (value === false) {
          form.$addControl(control);
          angular.forEach(control.$error, function(validity, validationToken) {
            form.$setValidity(validationToken, !validity, control);
          });
        } else {
          form.$removeControl(control);
        }
      });
    }
  }
})

DEMO

For more information and explanation of how it works. Check out my similar directive for excluding hidden elements from validation:

implementing a directive to exclude a hidden input element from validation ($addControl issue)

I think we could somehow combine these directives to create a general directive that could be used everywhere depending on how we evaluate an expression.

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, the $addControl and $removeControl possibly could do the trick. I'll try to sketch up a plunk that would disable validation for all children. The problem here is that there might by a ng-form somewhere between the disable-children and the inputs to disable, as well as not picking up select elements.
@RJo: yes, that's just a demo for your case and just to give the idea of $addControl and $removeControl. You could extend it. Happy coding.
@KhanhTO man can you help me in here: stackoverflow.com/q/32052991/1260751
4

As marmite suggests, ng-required can accept an expression so you can say something like

<input name="numeric" ng-required="alpha.disabled == false" />
<input name="alpha" ng-required="numeric.disabled == false" />

I'm not sure on how to check the disabled state - that ought to do it, but I've only ever created this effect by checking the state of a checkbox.

I realise this is a Lazarus post, but hopefully it will help others.

2 Comments

The ng-required is not the only validation for the fields, also patterns should be disabled. What I wanted was to turn off all validation for the field when not selected, not only required validation.
Oh lordy - that complicates things. What I have done is use ng-if to remove fields from the DOM that aren't current so they don't get validated, but as said, that requires a checkbox which does complicate the form. It may not be ideal for your intended UX, but it works OK.
0

I think that you are using ng-required incorrectly. You have hardcoded it to true for both text inputs but actually ng-required on those inputs should only be set true if the radio button is ticked.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.