我有一个像这样的指令,它用一个容器包装元素。
app.directive('myDirective', function($compile, $timeout) {
var num=0;
return {
link: function(scope, el, attrs) {
var uniqNum = scope.$index || num++;
var container = document.createElement('div');
container.className = "container";
el.wrap(container);
}
};
});
<textarea my-directive ng-repeat="str in arr track by $index" ng-model="arr[$index]">
</textarea>
但是,正如您在演示文稿http://plnkr.co/edit/wOulzF?p=preview中看到的那样,每当您开始在textarea中输入内容时,该元素就会移出容器。
如果ng-model不是arr,它可以正常工作。
任何人都可以解释这种行为吗?
答案 0 :(得分:1)
您对textarea
使用与ng-repeat
相同的模型。这意味着如果您更改textarea
的内容,则会同时更改ng-repeat
指令的模型。这反过来会导致ng-repeat
再次忙碌。
答案 1 :(得分:1)
您的指令在ngRepeat
之前运行。当Angular编译ngRepeat
时,它会在用作标记的代码中放置特殊注释。由于您的指令在添加到DOM之前运行,因此您的包装器不会包含这些重要注释。相反,最初创建的html如下所示:
<!-- ngRepeat: str in arr track by $index -->
<div class="container">
<textarea my-directive="" ng-repeat="str in arr track by $index" ng-model="arr[$index]" class="ng-scope ng-pristine ng-valid"> </textarea>
</div>
<!-- end ngRepeat: str in arr track by $index -->
更改arr
后,ngRepeat
会更新DOM,将新的/更新的ngRepeat
元素放置在Angular的标记(注释)所在的位置 - 这不在您的包装器中。因此,在更改arr
(并且发生$ digest)之后,您的html看起来像这样:
<!-- ngRepeat: str in arr track by $index -->
<textarea my-directive="" ng-repeat="str in arr track by $index" ng-model="arr[$index]" class="ng-scope ng-pristine ng-valid"> </textarea>
<div class="container"> </div>
<!-- end ngRepeat: str in arr track by $index -->
要解决此问题,请将指令优先级设置为1001或更高(ngRepeat的优先级为1000):
return {
priority: 1001,
link: function(scope, el, attrs) {.. }
}
现在ngRepeat
将首先操作DOM,所以当你的指令包装元素时,ngRepeat
注释也将被包装,导致以下html:
<div class="container">
<!-- ngRepeat: str in arr track by $index -->
<textarea my-directive="" ng-repeat="str in arr track by $index" ng-model="arr[$index]" class="ng-scope ng-pristine ng-valid"> </textarea>
<!-- end ngRepeat: str in arr track by $index -->
</div>
修复问题 - updated plunker