3

I am trying to add a ng-class attribute to a custom directive from the link function. But when using compile function after adding the ng-class attribute, It throws an error like "RangeError: Maximum call stack size exceeded"

Please see the code below

MyApp.directive('twinField',function($compile){
return {
    restrict:'A',
    require:'ngModel',
    scope:{
        fval:'='
    },
    link:function(scope,ele,attr,ctrl){
        ctrl.$validators.compareTo=function(val){
            //alert(scope.fval)
            return scope.fval==val
        }
        scope.$watch('fval', function(newValue, oldValue, scope) {
            ctrl.$validate()
        });
        ele.attr("ng-class","addForm.cpassword.$error.compareTo?'errorpswd':''")//=""
        $compile(ele)(scope);
    }
}

})

It is working when I add the ng-class directly in the html.

2
  • can you provide a fiddle Commented Jan 15, 2016 at 6:11
  • I guess, you shouldn't be using compile function in the link function, instead use link function in compile function. Also, compile function is called only one time. Commented Jan 15, 2016 at 7:24

1 Answer 1

8

$compile(ele)(scope); line in compiling directive element, which will leads to call compile your directive code in infinite loop, that's why it is giving “RangeError: Maximum call stack size exceeded” error.

Ideally you should use combination of compile and link function together. From compile function you need to add ng-class attribute & then remove the directive attribute to avoid directive element to compile indefinitely. Then compile your directive element with scope from directive link function.

Code

myApp.directive('twinField', function($compile) {
  return {
    restrict: 'A',
    require: 'ngModel',
    scope: {
      fval: '='
    },
    compile: function(tElement, tAttrs) {
      console.log(tElement)

      tElement.removeAttr('twin-field');

      return function(scope, ele, attr, ctrl) {
        ele.attr("ng-class", "addForm.cpassword.$error.compareTo?'errorpswd':''");
        ele.attr("test", "{{test}}':''");
        var compileFn = $compile(ele);
        ctrl.$validators.compareTo = function(val) {
          //alert(scope.fval)
          return scope.fval == val
        }
        scope.$watch('fval', function(newValue, oldValue, scope) {
          ctrl.$validate()
        });
        compileFn(scope);
      }
    }
  }
})

Similar answer

Demo here

But the other thing, I don't see any advantage with your code of adding and removing class using ng-class directive. As you are setting validity of your form control, implicitly you are adding and removing ng-valid-compare-to(on valid) & ng-invalid-compare-to(on invalid) class. So there is no need to create extra overhead to have ng-class logic to putting same thing again.

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

9 Comments

Actually i am adding ng-class attribute in the same tag which i added the custom drective. Compiling only inner elements dont resolve the ng-class attribute added in the custom directive tag right?
@Nijeesh I got what you are saying, I updated my answer.thanks :)
@Nijeesh did you get to time to look at the updated & linked answer,
Thanks @Pankaj Parker.The error is solved using your answer.I had to add a small change in your answer. tElement.removeAttr('twinField'); - tElement.removeAttr('twin-field');. But the added ng-class still not working.And it working when i added it to the html.
@Nijeesh did you look at reference answer..which has same thing..added ng-class from the directive
|

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.