destegabry
destegabry

Reputation: 23

Angular custom validator directive breaking other directives

I'm trying to build a directive for input fields which validates using a custom function passed from the outer scope, for example:

HTML:

<input type="text" custom-validator="checkValidity"/>

Controller:

$scope.checkValidity = function(value){
    return $scope.invalidWords.indexOf(value) === -1;
}

I've created a detailed plunker for this: http://plnkr.co/edit/H5A5O3?p=preview

Validation works, but it seems to broke things up with the default directives, in this case ng-disabled doesn't work and I can't access the variable used in ng-model!

This is my directive:

app.directive('customValidator', function() {   
   return {
      require: "ngModel"
    , scope: { customValidator: '='}
    , link: function postLink(scope, elm, attrs, ctrl) {
          var validator = function(value) {
            if(scope.customValidator && scope.customValidator(value)) {
              ctrl.$setValidity('custom-validator', true);
              return value;
            }
            ctrl.$setValidity('custom-validator', false);
            return undefined;
          }
          ctrl.$parsers.unshift(validator);
          ctrl.$formatters.unshift(validator);
        }      
   } 
});

I can't figure out what's going wrong, I really need help!

I should stay on Angular 1.0.7

Upvotes: 2

Views: 2413

Answers (2)

Mark Rajcok
Mark Rajcok

Reputation: 364687

ng-model and isolate scopes don't mix well, so follow @Codezilla's advice and don't create a new scope.

However, I suggest using $parse, which allows us to clearly specify in the HTML that we are passing a function with a single (named) argument to the directive:

<input type="text" ... custom-validator="checkValidity(val)">

app.directive('customValidator', function($parse) {
    return {
        require: "ngModel", 
        //scope: false, 
        link: function postLink(scope, elm, attrs, ctrl) {
            var validationFn = $parse(attrs.customValidator);
            var validator = function(value) {
                if(validationFn(scope, {val: value})) {
                    ctrl.$setValidity('custom-validator', true);
                    return value;
                }
                ctrl.$setValidity('custom-validator', false);
                return undefined;
            }
            ctrl.$parsers.unshift(validator);
            ctrl.$formatters.unshift(validator);
        }   
    }
});

plunker

Upvotes: 3

AlwaysALearner
AlwaysALearner

Reputation: 43947

The reason ng-disabled in not working on inputB is that you are creating a new scope through your directive:

scope: { customValidator: '=' }

To keep your model inputB in the same scope as inputA you can do something like this:

app.directive('customValidator', function() {
    return {
        require: "ngModel", 
        scope: false, 
        link: function postLink(scope, elm, attrs, ctrl) {
            var validator = function(value) {
                customValidator = scope[attrs["customValidator"]];  
                if(customValidator(value)) {
                    ctrl.$setValidity('custom-validator', true);
                    return value;
                }
                ctrl.$setValidity('custom-validator', false);
                return undefined;
            }
            ctrl.$parsers.unshift(validator);
            ctrl.$formatters.unshift(validator);
        }   
    }
});

Upvotes: 4

Related Questions