$compile'd指令中显示方法未执行

ng-show method not executing inside custom, $compile'd directive

本文关键字:显示 方法 执行 指令 compile      更新时间:2023-09-26

我继承了这个代码集,我想我明白发生了什么,但我似乎无法在自定义的$compile'd指令中获得ng-show。我怀疑它可能与gridster有关,但我已经尝试了您将看到的注释掉的行,以达到相同的效果。

这里是一个非常简化的版本,因为我不能使我正在工作的代码公开。我并不是真的在做一个恐龙应用,尽管那可能很好。

我不能为此使用templateUrl,因为我们需要将每个结果添加到gridster。还有更多的事情要做。请相信我不会:(

app.directive("tarpit", ["$compile", "gridster", function($compile, gridster) {
    return {
        scope: {
            dinosaurs: "="
        },
        restrict: "A",
        link: function(scope, element, attrs) {
            var i, dino;
            scope.$watch("dinosaurs", function(dinosaurs, oldDinosaurs) {
               for(i = 0; i < dinosaurs.length; i++) {
                   // scope.dinosaurs is set from a provider higher up our scope chain.  each dinosaur contains HTML
                  dino = angular.element(dinosaurs[i].html);
                  dino.attr("dinosaur-id", dinosaurs[i].id);
                  // i suspect these are the problem areas
                  dino = $compile(dino)(scope);
                  gridster.add(dino, dinosaurs[i].x, dinosaurs[i].y, dinosaurs[i].col, dinosaurs[i].row);
                  // i've also tried the following which didnt work
                  // element.append(dino);
               }
            }
        }
    };
}]);
app.directive("dinosaur", function() {
   return {
      scope: {
          dinosaurs: "="
      },
      restrict: "A",
      link: function(scope, element, attrs) {
          scope.isExtinct = function() {
              // there's more to it than this but you get the idea
              for(var i = 0; i < scope.dinosaurs.length; i++) {
                  if(scope.dinosaurs[i].id == attrs.dinosaurId) {
                     return true;
                  }
              }
              return false;
          };
      }
   };
});

页面开头为:

<div tarpit dinosaurs="dinosaurs"></div>

当恐龙web服务结束时,我们点击$watch,页面最终将变成:

<div tarpit dinosaurs="dinosaurs">
     <div dinosaur dinosaurs="dinosaurs" dinosaur-id="111">
         <div ng-show="isExtinct()">I'm dead</div>
         <div ng-show="!isExtinct()">It's a miracle</div>
     </div>
     ...
     <div dinosaur dinosaurs="dinosaurs" dinosaur-id="999">
         <div ng-show="isExtinct()">I'm dead</div>
         <div ng-show="!isExtinct()">It's a miracle</div>
     </div>
</div>

问题是永远不会调用isExtinct方法。

我尝试了以下操作,得到了相应的结果:

  1. 移动到'tarpit' -它被执行,但我失去了我是哪种恐龙的背景。我试图传递$element到它,但它仍然未定义。
  2. ng-show = " $ parent.isExtinct()"-它不会被调用。
  3. 使用标志而不是方法。与上面的结果相同。
  4. 把isExtinct放到tarpit指令中的controller()中。结果与#1相同。方法被调用了,但是不知道是哪只恐龙调用了它。
在这一点上,我将满足于#1,只要我能够保持我是哪种恐龙的想法,例如将$element传递给父方法,或者甚至只是attr1 . dinosaurid。我不能依赖它们被追加映射到恐龙数组的顺序,因为gridster会重新排列它们

我明白了。问题的根源在这行:

              dino = $compile(dino)(scope);

在这里,我们正在创建恐龙指令,我们正在使用tarpit作用域这样做。当我们后来做

              scope.isExtinct = function() { ... }

这里的'scope'在dinosaur指令中,但由于某种原因,isExtinct在ng-show中无法访问,我猜是因为ng-show位于Tarpit作用域,而isExtinct位于dinosaur作用域。这只是猜测。这似乎意味着我们在说tarpit。ngShow = tarpit.isExtinct。限定。isExtinct不存在(但没有错误提示),所以它是未定义的,ng-show="undefined"是有效的,所以它不会向我们大喊大叫。这就是为什么在$parent上创建isExtinct解决了这个问题,因为现在tarpit了。isExtinct确实存在。这也意味着不那么严格地隔离作用域将允许正常的继承为我们解决这个问题。

鉴于此,我找到了两个解决方案:

             scope.$parent.isExtinct = function() { ... }

             scope: true

因为我需要的任何数据都是作为属性传递进来的,所以我能够通过attrs而不是作用域值来消费我需要的一切。最后我只使用

             scope: true