从该指令内部监视Angular指令上的类时出现奇怪的行为

时间:2015-06-27 23:15:32

标签: javascript angularjs

我试图通过我的Angular指令监视特定类当前是否在元素上。切换添加或删除该类的$ scope变量将触发指令更新一些内容。

但我所看到的是,第一次切换不会采取,但随后的切换不会。因此更新不同步。这是一个使用Monitor for class changing on element in AngularJS directive解决方案的简化示例。这里发生了什么,如何让类更改在指令中保持同步?非常感谢!

CodePen example

HTML:

<div ng-app="myApp" ng-controller="myCtrl">
  <label>
    <input type="checkbox" ng-model="compact" /> Compactify
  </label>
  <div>Compactify is set to: {{compact}}</div>
  <div firefly class="crewList" ng-class="{compact: compact}"></div>
</div>

JS:

var app = angular.module('myApp', []);

app.controller('myCtrl', ['$scope', function($scope) {
  $scope.compact = false;
}]);

app.directive('firefly', [function() {
  return {
    restrict: 'AE',
    template: '<ul ng-class="{compact: compacted}"><li>Capt. Mal</li><li>Zoe</li><li>Wash</li><li>Kaylee</li><li>Book</li><li>Inara</li><li>Jayne</li><li>Simon</li><li>Spoilers, sweetie!</li></ul>',
    link: function(scope, element, attrs) {
      scope.insideCompactor = function() {
        scope.compacted = element.hasClass('compact');
      };
      scope.insideCompactor();
      scope.$watch(function() {return element.attr('class');}, function(newValue) {
        scope.insideCompactor();
      });
    }
  };
}]);

CSS:

.crewList {font-size: 2rem;}
.crewList UL.compact {font-size: 1rem;}

更新 虽然我还没弄清楚如何做到这一点,但我确实想出了更多关于这个问题的信息。作为摘要周期的一部分,指令中的$ watch似乎在之前触发实际应用于元素本身。因此,指令的范围变量与元素上的实际内容不同步。

1 个答案:

答案 0 :(得分:0)

Working Code Pen

您可以尝试将模型值传递给指令。我删除了ng-class指令并将其替换为class-model属性,以将数据传递给指令。

<div firefly class="crewList" class-model="compact"></div>

然后可以在指令范围内引用该值,并且可以直接监视该值而不是检查该元素是否具有该类。

app.directive('firefly', [function() {
  return {
    restrict: 'AE',
    template: '<ul ng-class="{compact: compacted}"><li>Capt. Mal</li><li>Zoe</li><li>Wash</li><li>Kaylee</li><li>Book</li><li>Inara</li><li>Jayne</li><li>Simon</li><li>Spoilers, sweetie!</li></ul>',
    scope: {
      classModel: '='
    },
    link: function(scope, element, attrs) {
      scope.insideCompactor = function() {
        scope.compacted = scope.classModel;
      };
      scope.insideCompactor();
      scope.$watch('classModel', function(newValue) {
        scope.insideCompactor();
      });
    }
  };
}]);