使用 ng-repeat 在 link 中手动嵌入

Manual transclude in link with ng-repeat

我有一个 angular 应用程序,它使用 ng-repeat-start 来显示一些动态信息。

<div>
  <table>
    <tbody>
      <tr my-directive ng-repeat="data in vm.data">
        <td ng-bind="data.id"></td>    
        <td ng-bind="data.id"></td>    
      </tr>
        <tr ng-repeat-end>
        <td>extrarow</td>
      </tr>
    </tbody>
  </table>
</div>

我还构建了一个指令,我想用它根据某些数据的值将 class 应用于整个 tr 。我想使用 link 而不是使用 $watch。

因为里面本身可以包含很多,所以我想用transclude来做这个。我不希望将标签插入到我的 table 中,因为这会破坏我的所有样式,所以我必须手动执行此操作,如下所示:

function myDirective() {
    return {
       transclude: true,
       scope: {},
       link: function($scope, $element, $attrs, $ctrl, $transclude) {
          var cloned = $transclude();
          $element.append(cloned);              
       }
    }
}

问题是这没有按预期工作。克隆的对象仅附加到 ng-repeat 的最后一行。这可能是由于 $element 对象,但我不确定。

我在这个jsfiddle中重现了这个问题。

对问题出在哪里有任何想法吗? 非常感谢。

如果您只想根据您的内容添加 class,您可以使用 ng-class

<td ng-bind="data.id" ng-class="{'myClass': data.id > 4}"></td>  

编辑

您可以使用一次性绑定,这样您就不必绑定很多 $watchers

<td ng-bind="data.id" ng-class="::{'myClass': data.id > 4}"></td> 

在您的指令中将 transclude 设置为 false 将为您提供整个列表。

如果您想 运行 您编写的另一个自定义 ng-repeat 指令,您可以为 ng-repeat 指令设置不同的优先级。低于默认 ng-repeat 指令的优先级将导致它在默认 ng-repeat 之后 运行。

我已经用一个示例更新了你的 jsFiddle, https://jsfiddle.net/1x08vxpm/15/

angular.module('app', [])

.controller('Controller', Controller)    
.directive('ngRepeat', ngRepeat);

function ngRepeat() {
    return {    
       priority: 0,
       scope: {},
       link: function($scope, $element, $attrs) {
          $element.css('color', 'red');
       }
    }
}

我很困惑为什么你需要嵌入。我认为this is what you're looking for;但是我不得不说,我不相信 $observe 比 $watch 更经济。

对于 $observe,我在 TR 中添加了以下内容:

 <tr my-directive data-value="{{data.id}}" ng-repeat="data in vm.data"> 

并且该指令在某些条件下演示了 class 更改。

function myDirective() {
      return {
        link: function($scope, element, attrs) {
          attrs.$observe('value', function(val) {
            if (val && val == "9.2")
              element.addClass("myClass");
            else
              element.removeClass("myClass");
          });              
       }
    }
  }