1

I use an angular directive to change the form input validity as soon as the user starts to fill the input :

angular.module('core').directive('serverError', function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, element, attrs, ctrl) {
      element.on('input', function() {
        scope.$apply(function() {
          ctrl.$setValidity('server', true);
        });
      });
      element.on('change', function() {
        scope.$apply(function() {
          ctrl.$setValidity('server', true);
        });
      });
    }
  };
});

My form is :

<input type="text" data-ng-model="request.lastname" name="lastname" required server-error/>
<div ng-show="form.lastname.$error.server">
    <span>Please fill this field</span>
</div>

<input type="radio" data-ng-model="request.civility" name="civility" value="M" required server-error> M.
<input type="radio" data-ng-model="request.civility" name="civility" value="F" required server-error> Mme
<input type="radio" data-ng-model="request.civility" name="civility" value="MISS" required server-error> Mlle
<div ng-show="form.civility.$error.server">
  <span>Please fill this field</span>
</div>

It works correctly for the text inputs but it doesn't work for the radio buttons. Only the last radio button works as expected and make the error disappears.

Any idea to resolve this problem?

Thanks.

2 Answers 2

2

Unfortunately, when a control with ng-model is registered with the form, it will register as a property of the form using the name of the input.

In your case, all your 3 radio buttons use the same name (civility) => the first radio is overwritten by the second input and the second input is overwritten by the third input.

Try a workaround using different names for your radio inputs:

<input type="radio" data-ng-model="request.civility" name="civility1" value="M" required server-error>M.
<input type="radio" data-ng-model="request.civility" name="civility2" value="F" required server-error>Mme
<input type="radio" data-ng-model="request.civility" name="civility3" value="MISS" required server-error>Mlle
<div ng-show="form.civility1.$error.server && form.civility2.$error.server && form.civility3.$error.server">
    <span>Please fill this field</span>
</div>

DEMO

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

Comments

0

Since having a different name for each radio voids the meaning of radio groups and makes auto-filling forms unavailable, there is a better workaround for that:

Basically you have to get the NgModelController using angulars jQuery-Lite.

 
Using your directive that may look like this (I did not test that code):

angular.module('core').directive('serverError', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, element, attrs, ctrl) {
            function updateValidity() {
                const ngModelCtrl = element.controller('ngModel');
                if (ngModelCtrl) {
                    ngModelCtrl.$setValidity('server', true);
                }
            }

            element.on('input', updateValidity);
            element.on('change', updateValidity);
        }
    };
});

 
I had the same problem after trying to evaluate a validation response from the server and trying to set the validity from there.
I did not use directives. I previously tried to set the validity using my components FormController something like formCtrl[inputName].$setValidity(...), but ended up with the exact same behaviour as described in the question.
So I had to change it to this (tested and working):

function updateValidity(control) {
    // `control` resembles `formCtrl[inputName]` as a parameter
    angular.element('input[name="' + control.$name + '"]').each((i, elem) => {
        const ngModelCtrl = angular.element(elem).data().$ngModelController;
        if (ngModelCtrl) {
            ngModelCtrl.$setValidity('server', true);
        }
    });
}

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.