我写了一个简单的指令,能够动态设置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行时,它会显示相应的次数,所以我认为它与此有关,但我不知道如何修复它。有任何想法吗?谢谢!
答案 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()
。