Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I force an angular validation directive to run?

I've created a validation directive for my form. It basically validates a fields value based on data from another field.

It works perfect :-)

My problem is that if the other field changes after the validation was executed, the validation will not run again.

var myApp = angular.module('myApp', [])

.directive('validateInteger', function() {
  return {
    require: 'ngModel',
    link: function(scope, elm, attrs, ctrl) {
      ctrl.$parsers.unshift(function(viewValue) {
          var int1val = scope.int1;
          scope.int2valid = (viewValue > int1val) ? "valid" : undefined;
          if (scope.int2valid == "valid") {
              ctrl.$setValidity('higher', true);
              return viewValue;
          } else {
              ctrl.$setValidity('higher', false);
              return undefined;
        }
      });
    }
  };
});

jsfiddle: http://jsfiddle.net/hanspc/vCFFQ/

like image 402
hansch Avatar asked Jun 02 '13 17:06

hansch


People also ask

What is dirty validation in angular?

ng-dirty The field has been modified. ng-valid The field content is valid. ng-invalid The field content is not valid. ng-valid-key One key for each validation.

How does user validate data in AngularJS?

The first method is by using validation control states which include the form sate and input state. The other method is using CSS classes. Form State and Input State: The state of the form and the input fields are updated by AngularJS and these states are used to show useful messages to the user.

What is pristine in angular?

pristine: This property returns true if the element's contents have not been changed. dirty: This property returns true if the element's contents have been changed. untouched: This property returns true if the user has not visited the element.

How do I add validation in template-driven form?

To add validation to a template-driven form, you add the same validation attributes as you would with native HTML form validation. Angular uses directives to match these attributes with validator functions in the framework.


1 Answers

It is a really bad idea to refer explicitly to some fields in your directive. As you can see, this has a lot of drawbacks : unportability, code repetition, brittleness, …

Just make something like that :

<input type="text" ng-model="int2" validate-greater-integer="int1" />

And :

myApp.directive('validateGreaterInteger', function() {
    return {
    require: 'ngModel',
    scope: {
        otherInteger : '=validateGreaterInteger',
    }
    link: function(scope, elm, attrs, ctrl) {
        ctrl.$parsers.unshift(function(viewValue) {
        if (viewValue > scope.otherInteger) {
            ctrl.$setValidity('higher', true);
            return viewValue;
        } else {
            ctrl.$setValidity('higher', false);
            return undefined;
        }
    }
});

You can then simply do the typical state control (see the section "Binding to form and control state" for an exemple).

Please notice that, in this case, you can also more simply use input[number] and its min parameter.


Edit after the discussion in comments :

Well, the functions in NgModelController.$parsers are obviously called only when the content of the model changes. What you want to do is to make validation whenever int1 or int2 change. So just do it :-) :

link: function(scope, elm, attrs, ctrl) {
    scope.$watch('data', function (data) {
      if (data.int2 > data.int1) {
          ctrl.$setValidity('higher', true);
          return data.int2;
      } else {
          ctrl.$setValidity('higher', false);
          return undefined;
    }
  }, true);

Use your own validation variable (int2valid in your Fiddle) is also very strange. Please use the typical state control, with something like form.int2.$error.higher.

like image 98
Blackhole Avatar answered Oct 11 '22 17:10

Blackhole