与ng-repeat相同的HTML元素上的AngularJS Custom指令

时间:2014-08-12 21:15:59

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

我写了一个简单的指令,能够动态设置ng-model的值,如其他Stack Overflow问题所述:AngularJS - bind ng-model to a variable which name is stored inside another variable。这很好用,除非我在一个也有ng-repeat的元素上使用它。它被渲染太多次,并且DOM看起来不正确。

指令:

angular.module( 'dynamicModel-directive', [] )
.directive( 'dynamicModel', function( $compile ) {
    return {
        link: function( scope, element, attr ){
            element[0].removeAttribute( 'dynamic-model' );
            element[0].setAttribute( 'ng-model', scope.$eval( attr.dynamicModel ) );
            $compile( element[0] )( scope );
        }
    };
});

HTML(通过渲染输入框而不是按钮组来简化):

<div ng-if="field.type == 'buttonGroup'">
     <input type="text" ng-repeat="option in field.options"
           dynamic-model="field.name" class="form-control">
</div>

上面的代码会显示四个输入框,即使field.options中只有两个项目。

以下是生成的DOM的样子:

<div ng-if="field.type == 'buttonGroup'" class="ng-scope">
<!-- ngRepeat: option in field.options -->
<!-- ngRepeat: option in field.options -->
<input type="text" ng-repeat="option in field.options" class="form-control ng-scope ng-pristine ng-valid" ng-model="application.insured.gender">
<!-- end ngRepeat: option in field.options -->
<input type="text" ng-repeat="option in field.options" class="form-control ng-scope ng-pristine ng-valid" ng-model="application.insured.gender">
<!-- end ngRepeat: option in field.options -->
<!-- end ngRepeat: option in field.options -->
<!-- ngRepeat: option in field.options -->
<input type="text" ng-repeat="option in field.options" class="form-control ng-scope ng-pristine ng-valid" ng-model="application.insured.gender">
<!-- end ngRepeat: option in field.options -->
<input type="text" ng-repeat="option in field.options" class="form-control ng-scope ng-pristine ng-valid" ng-model="application.insured.gender">
<!-- end ngRepeat: option in field.options -->
<!-- end ngRepeat: option in field.options -->

当我在指令中注释掉$ compile行时,它会显示相应的次数,所以我认为它与此有关,但我不知道如何修复它。有任何想法吗?谢谢!

1 个答案:

答案 0 :(得分:4)

这是因为ng-repeat被多次编译。

您可以设置terminal标记并将priority提升为高于ng-repeat,以确保ng-repeat只会被编译一次。

.directive('dynamicModel', function ($compile) {
  return {
    terminal: true, // prevent ng-repeat from compiled twice
    priority: 1001, // must higher than ng-repeat
    link: function (scope, element, attrs) {
      attrs.$set('ngModel', scope.$eval(attrs.dynamicModel));
      attrs.$set('dynamicModel', null);
      $compile(element)(scope);
    }
  };
});

PS。有attrs.$set()