1

I did this directive to validate a number if it is in a range:

app.directive('nkNumber', function(){
  return {
    scope: {
      max: '=nkMax',
      min: '=nkMin'
    }, 
    require: 'ngModel', 
    restrict: 'A',
    link: function($scope, iElm, iAttrs, controller) {
      function validate(value){
        if (angular.isDefined(value)){
          value = parseInt(value);
          if ($scope.max){
            var max = parseInt($scope.max);
            controller.$setValidity('nkMax', value < max)
          }
          if ($scope.min){
            var min = parseInt($scope.min);
            controller.$setValidity('nkMin', value > min)
          }
        }
        return value;
      }
      controller.$parsers.push(validate);
      controller.$formatters.push(validate);
    }
  };
});

The validation works fine, but my model isn't updated when I change the value on the input.

Why is this happening? How can I solve it?

2

1 Answer 1

4

You are probably using a version of angular prior to 1.2.x. Older versions of angular handled isolate scope inconsistently, often swallowing other directives into the isolate scope. This is what is happening in your case.

The ng-model is acting on the isolate scope of your nk-number directive, so it is writing it's value into this private scope rather than the outer scope.

If you are using 1.2.x version of angular, the isolate scope does not mix like this, so things should work as expected.

The fix if you want to remain in an older version of angular is to not use isolate scope at all for this particular directive.

In general, it is almost always a bad idea to use isolate scope unless your directive has a template. If your directive does not have its own template, the use of isolate scope is hardly ever justified and can cause the sort of problems that you are seeing.

Here is an example of your directive written without isolate scope:

app.directive('nkNumber', function($parse){
  return {
    require: 'ngModel', 
    restrict: 'A',
    link: function($scope, iElm, iAttrs, controller) {

      function validate(value){
        var max = $scope.$eval(iAttrs.nkMax);
        var min =  $scope.$eval(iAttrs.nkMin);

        if (angular.isDefined(value)){
          value = parseInt(value);
          if (max){
            max = parseInt(max);
            controller.$setValidity('nkMax', value < max)
          }
          if ($scope.min){
            min = parseInt(min);
            controller.$setValidity('nkMin', value > min)
          }
        }
        return value;
      }
      controller.$parsers.push(validate);
      controller.$formatters.push(validate);
    }
  };
});

notice that without isolate scope you need to use $scope.$eval() on the nkMax and nkMin attributes.

This actually the better way to write this directive, and will work in all versions of angular.

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

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.