AngularJs范围参考与指令
我想在Angular中编写一个非常简单的3星评分系统,但是当使用对数组中的项目的引用时,我遇到了指令范围的问题。AngularJs范围参考与指令
为了测试我的标记看起来像这样:
<div id="ref">
<span>Reference to item 1: </span>
<item-score ng-model="selected.score"></item-score>
</div>
<div ng-repeat="item in items track by $index">
<div class="row">
<span>{{item.name}}:</span>
<item-score ng-model="item.score"></item-score>
<item-score ng-model="item.score"></item-score>
</div>
</div>
而且我的JavaScript已被简化,但做同样的事情:
var App = angular.module('testApp', []);
App.controller('MainCtrl', ['$scope', function ($scope) {
$scope.items = [
{ id: 1, score: 1, name: 'Item 1' },
{ id: 2, score: 2, name: 'Item 2' },
{ id: 3, score: 1, name: 'Item 3' }
];
$scope.selected = $scope.items[1];
}]);
App.directive('itemScore', function() {
return {
restrict: 'E',
require: '?ngModel',
replace: true,
template: '<div class="score"><i class="fa fa-star" ng-click="set($index+1)"' +
' ng-repeat="star in stars track by $index" ' +
'ng-class="{ yellow: star === true }"></i></div>',
link: function (scope, elm, attrs, ctrl) {
var num = 5;
scope.stars = new Array(num);
scope.set = function (score) {
if (ctrl.$viewValue === score) { score--; }
ctrl.$setViewValue(score);
};
function setStars() {
for (var i = 0; i < num; i += 1) {
scope.stars[i] = ((i+1) <= ctrl.$viewValue ? true : false);
}
}
ctrl.$render = function() {
setStars();
};
}
}
});
我创建了一个plunker http://plnkr.co/edit/QIXc1Nw68q7Zt1gsoa2P?p=preview
时点击行中的每个分数框都会正确更新,但是当你点击行上面的星号(使用对数组中第二项的引用)时, l更新行中的两个指令,但不会自行更新。
我需要该指令来处理一个引用,因为该项目被传递到另一个指令以在模态窗口内使用(我的应用程序具有与plunker相同的行为)。
任何帮助,将不胜感激提前。
当您单击每行内部的分数框时,两者都会正确更新,因为两个指令都在观察同一个属性。所以当其中一条指令改变了启动次数时,另一条指令会被通知这个改变并强制渲染。由于这两个指令都在相同的ng-repeat
范围内,因此两个评分框都会重新呈现。
尝试从ng-repeat
中的行中移除其中一个指令,您将注意到它将不再正确更新。
解决此问题的一种方法是在设置视图值后调用ctrl.$render()
。就像这样:
scope.set = function (score) {
if (ctrl.$viewValue === score) { score--; }
ctrl.$setViewValue(score);
ctrl.$render();
};
另一种选择是定义在scope
一个ng-model
参考,并直接对其进行更新。
require : 'ngModel',
scope: {
ngModel: '=?'
}
然后:
scope.set = function (score) {
scope.ngModel = score;
};
谢谢,这样一个简单的解决方案。在我们的主应用程序中调用$ render()似乎更可靠。 – 2014-09-04 13:28:47
我认为你应该改变方法,你应该使用的方式结合指令,并以这种方式传递模型。 – bmazurek 2014-09-04 12:19:30