【问题标题】:ng-show method not executing inside custom, $compile'd directiveng-show 方法未在自定义、$compile'd 指令中执行
【发布时间】:2014-08-13 18:37:58
【问题描述】:

我继承了这个代码集,我想我理解发生了什么,但我似乎无法在自定义的 $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>

当恐龙网络服务完成并且我们点击 $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. 将 isExtinct 移至 'tarpit' - 它被执行,但我失去了我是哪种恐龙的上下文。我尝试将 $element 传递给它,但它仍然未定义。
  2. ng-show="$parent.isExtinct()" - 它不会被调用。
  3. 使用标志而不是方法。结果与上述相同。
  4. 将 isExtinct 放入 tarpit 指令内的 controller() 中。结果与#1 相同。该方法被调用,但不知道是哪个恐龙调用了它。

此时我会满足于#1,只要我能保持对我是哪种恐龙的想法,例如将 $element 传递给父方法,甚至只是 attr.dinosaurId。 我不能依赖将它们附加到恐龙数组的顺序,因为 gridster 会重新排列它们。

【问题讨论】:

  • 1.你在使用角度兼容的网格吗? (即:angular-gridster)2.您没有使用模板字符串或模板网址是否正确?
  • 是的,正在使用角度兼容的网格。正确,我不能使用模板或 templateUrl。 HTML 需要作为字符串使用。

标签: javascript angularjs gridster


【解决方案1】:

我想通了。问题的根源就在线上:

              dino = $compile(dino)(scope);

在这里,我们正在创建恐龙指令,并且我们正在使用 tarpit 范围这样做。后来我们做了

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

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

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

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

             scope: true

由于我需要的任何数据都作为属性传入,因此我能够通过 attrs 而不是范围值来使用我需要的一切。我最后只是使用

             scope: true

【讨论】:

    猜你喜欢
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多