Tympanix
Tympanix

Reputation: 113

Angularjs: Compile ng-repeat dynamically

I have found some strange behavior with Angularjs. My directive simply adds and compiles ng-repeat to my dom element. However the scope variable item is not accessible. Look at the code below for explanation.

var demo = angular.module('demo', []);
demo.directive('customRepeat', function($compile) {
    return {
      priority: 2000,
      restrict: 'A',
      compile: function(element){
        element.attr('ng-repeat', 'item in [1,2,3,4,5,6]')
          
        return function(scope, element) {
          $compile(element)(scope)
        }
      }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app='demo'>
    <h3>My Items</h3>
    <div custom-repeat>
      Item: {{item}}
    </div>
</div>

Who has some Angularjs skills to figure this one out?

N.B. Try and run this with an older version of Angularjs (say 1.2.x) and you will see that it works as intended.

Upvotes: 2

Views: 2322

Answers (1)

Pankaj Parkar
Pankaj Parkar

Reputation: 136144

The correct way to compile directive when raw DOM is modified is, create compileFn from directive compile function like var compileFn = $compile(element) and then inside link function recompile element with liked scope. That way you will also see Maximum call stack exceed error in both Angular 1.2.X & 1.6.X version. Check this plunker by opening console.

Basically what happening is, you are adding an ng-repeat on directive element & recompiling that element once again which will lead to compilation of customDirective once again, and this process will keep on happening infinitely. So before compiling element once again, you should make sure that you had removed custom-report directive attribute. That will not allowed to custom-report infinite execution.

var demo = angular.module('demo', []);
demo.directive('customRepeat', function($compile) {
    return {
      priority: 2000,
      restrict: 'A',
      compile: function(element){
        element.attr('ng-repeat', 'item in [1,2,3,4,5,6]')
        element.removeAttr('custom-repeat');
        //this line is need for compilation of element
        var compile = $compile(element);
        return function(scope, element) {
          compile(scope); //linking scope
        }
      }
    }
});

Plunker Demo

Upvotes: 1

Related Questions