【问题标题】:My directive is executed before ngRepeat and ngInclude, despite of default priority 0尽管默认优先级为 0,但我的指令在 ngRepeat 和 ngInclude 之前执行
【发布时间】:2015-03-25 20:18:19
【问题描述】:

我的自定义指令编译函数在 ngRepeat (priority=1000) 和 ngInclude (priority=400) 之前执行,尽管默认优先级是 0,所以它应该在之后执行。

片段显示 myDir 指令附加的内容丢失,仅显示来自 ngInclude 模板的包含内容:

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>

我在这里的 jsfiddle 中有相同的代码:jsfiddle-link 在那里它显示了预期的行为。显示了来自指令的附加文本。 因为在 ngRepeat 和 ngInclude 编译函数之后附加了最低优先级的文本。

示例之间的区别仅在于角度版本。 Snipped here 在 v1.2.23 上运行(与我在运行 v1.3.0 的项目中的行为相同)并且 jsfiddle 在 v1.2.1 上运行

欢迎任何建议,在此先感谢 ;)

PS:在jsfiddle示例中,视图中缺少“&lt;span&gt;Number {{$index}}&lt;/span&gt;”部分,告诉我原因的人会加分。

【问题讨论】:

  • 我知道如何绕过这个问题,但在我看来它是 angularjs 中的错误,不是吗?
  • 是问题:“为什么 Angular 版本之间的行为存在差异”还是问题“我如何使用 Angular ver. Y 完成 X”?
  • 为什么 Angular v1.2.23+ 忽略指令优先级并在更高优先级的 inbuild 指令 ngInclude 和 ngRepeat 之前运行最低优先级的自定义指令,这会破坏文档?

标签: javascript angularjs angularjs-directive angularjs-ng-repeat angularjs-ng-include


【解决方案1】:

他们似乎添加了ngIncludeFillContentDirective 指令(也注册在ngInclude 名称下),它替换了整个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);
      }
    };
  }];

它以 -400 的优先级运行,因此您的指令在 ngRepeat 和 ngInclude 之后但在此之前执行。

【讨论】:

  • 我试图将 myDir 指令的优先级设置为 -500 以在 ngIncludeFillContentDirective 之后执行,但没有任何改变:/(我没有意识到优先级可以是负值,谢谢 :))但你至少给了我我可以调查更多的痕迹。所以谢谢你!
  • 我看不到 ngInclude 是如何使用 ngIncludeFillContentDirective... 我看到 ngIncludeFillContentDirective 已定义并且需要 ngInclude 但它是如何被执行的?
  • 它们都以相同的名称注册ngInclude,因此当在元素上找到ng-include 属性时,Angular 会同时应用它们
  • 啊哈,我现在找到了,谢谢..我不知道可以做到..在同名下注册多个指令。
【解决方案2】:

我不确定,但我认为问题在于 ngInclude 是终端。

ngdocumentation

终端

如果设置为 true 则当前优先级将是最后一组 将执行的指令(当前优先级的任何指令 仍将执行,因为相同优先级的执行顺序是 不明确的)。请注意,在 指令的模板也将被排除在执行之外。

这是我的解决方法(链接 fn 中的 DOM 操作而不是编译 fn):

angular.module("app", [])
.run(function($templateCache) {
  $templateCache.put('test.html', '<p>Content included by ngInclude</p><span>Number {{$index}}</span>');
})
.directive("myDir", function($compile) {
    return {
        link: function(scope, elm){
            elm.append($compile('<br><span>apended by directive myDir, 1+1={{1+1}}</span>')(scope));
        }
    };
})
.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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 2019-08-08
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多