Search code examples
javascriptangularjsangularjs-directiveangularjs-ng-repeatangularjs-ng-include

My directive is executed before ngRepeat and ngInclude, despite of default priority 0


My custom directives compile function is executed before ngRepeat (priority=1000) and ngInclude (priority=400), despite of default priority is 0, so it should be executed after.

Snippet shows that content appended by myDir directive is missing, only shows included content from ngInclude template:

angular.module("app", [])
.run(function($templateCache) {
  $templateCache.put('test.html', '<p>Content included by ngInclude</p><span>Number {{$index}}</span>');
})
.directive("myDir", function() {
    return {
        compile: function(elm){
            elm.append('<span>apended by directive myDir, 1+1={{1+1}}</span>');
            return function link(){};
        }
    };
})
.controller("myApp", function($scope){
    $scope.items = [1,2,3];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myApp">
    <div ng-repeat="item in items" my-dir="" ng-include="'test.html'"><p>First content</p></div>
</div>

I have same code in jsfiddle here: jsfiddle-link There it shows expected behaviour. Appended text from directive is shown. Because of lowest priority text is appended after ngRepeat and ngInclude compile functions.

Difference between examples is in angular versions only. Snipped here runs on v1.2.23 (same behaviour as in my project running v1.3.0) and jsfiddle runs on v1.2.1

Any advice is welcome, thanks in advance ;)

PS: In jsfiddle example, there is "<span>Number {{$index}}</span>" part missing in view, extra score for those who tell me why.


Solution

  • It seems they added the ngIncludeFillContentDirective directive (also registered under the ngInclude name), which replaces the entire html:

    var ngIncludeFillContentDirective = ['$compile',
      function($compile) {
        return {
          restrict: 'ECA',
          priority: -400,
          require: 'ngInclude',
          link: function(scope, $element, $attr, ctrl) {
            if (/SVG/.test($element[0].toString())) {
              // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
              // support innerHTML, so detect this here and try to generate the contents
              // specially.
              $element.empty();
              $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
                  function namespaceAdaptedClone(clone) {
                $element.append(clone);
              }, {futureParentElement: $element});
              return;
            }
    
            $element.html(ctrl.template);
            $compile($element.contents())(scope);
          }
        };
      }];
    

    It runs on priority -400, so your directive is executed after ngRepeat and ngInclude but before this one.