2014-09-04 83 views
2

我想在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相同的行爲)。

任何幫助,將不勝感激提前。

+0

我認爲你應該改變方法,你應該使用的方式結合指令,並以這種方式傳遞模型。 – bmazurek 2014-09-04 12:19:30

回答

0

當您單擊每行內部的分數框時,兩者都會正確更新,因爲兩個指令都在觀察同一個屬性。所以當其中一條指令改變了啓動次數時,另一條指令會被通知這個改變並強制渲染。由於這兩個指令都在相同的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; 
}; 
+0

謝謝,這樣一個簡單的解決方案。在我們的主應用程序中調用$ render()似乎更可靠。 – 2014-09-04 13:28:47