$ watchCollection不更新页面上的数组长度

时间:2016-03-08 16:17:11

标签: javascript angularjs

我试图为用户拥有的警报数设置一个计数器。如果我在console.log $ scope.alerts和$ scope.count,我可以看到两者都在更新,但使用{{alerts.length}}或{{count}}作为#msgCount的值只会给我pageLoad上的初始计数,并且当数组长度发生变化时不会更新。我做错了什么?

我的控制器:

myApp.controller('globalAlerts', ['$scope', '$http', function ($scope, $http) {
        $scope.alerts = [{
    "type": "warning",
    "msg": "This is a generic alert. It is best suited for one or two line messages."
},
{
    "type": "danger",
    "msg": "<strong>Past Due!</strong> You have an invoice <a class=\"invoice-link\" href=\"\">192607</a> that is past due. <a href=\"invoices.html\">View all invoices.</a>"
},
{
    "type": "success",
    "msg": "This green alert indicates something positive occurred. Doesn't that make you feel happy?"
},
{
    "type": "info",
    "msg": "This blue alert is another generic warning usually used to inform. Isn't it soothing?"
}
];
    $scope.$watchCollection('alerts.length', function() {
        return $scope.alerts.length;

    }, true);
    $scope.closeAlert = function(index) {
      $scope.alerts.splice(index, 1);
    };



    $scope.dynamicPopover = {
            templateUrl: 'partials/alerts/globalAlerts.html',
            title: 'Recent Alerts'
    };

}]);

标记:

<div id="upperNav" ng-controller = "globalAlerts">
        <a class="btn btn-link" id="msg" popover-placement="bottom" uib-popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" >
        <div class="badge badge-warning" id="msgCount">{{alerts.length}}</div>
        ALERTS</a></div>

使用popover标记:

<div id="alertCntr" ng-controller = "globalAlerts">
         <uib-alert ng-show="alerts.length" ng-repeat="alert in alerts track by $index" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>  
         <p ng-hide="alerts.length">You ain't got no more alerts, kid!</p>   
</div>

4 个答案:

答案 0 :(得分:1)

对于其他用户:

HTML指定每个块都有自己的控制器。这意味着2个控制器是独立的,并且不知道何时触摸了彼此的警报阵列。

最简单的解决方案是嵌套HTML,以便共享控制器:

<div id="upperNav" ng-controller = "globalAlerts">
    <a class="btn btn-link" id="msg" popover-placement="bottom" uib-popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" >
    <div class="badge badge-warning" id="msgCount">{{alerts.length}}</div>
    ALERTS</a>
    <div id="alertCntr">
       <uib-alert ng-show="alerts.length" ng-repeat="alert in alerts track by $index" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>  
       <p ng-hide="alerts.length">You ain't got no more alerts, kid!</p>   
     </div>
</div>

修改

更新了完全符合您要求的plnkr:http://plnkr.co/edit/AIwGi7eIzilsGGL7Us3G?p=preview

答案 1 :(得分:0)

您在监视功能后添加了另一个参数。像这样。

$scope.$watchCollection('alerts.length', function() {
    $scope.count = $scope.alerts.length;
    return $scope.count;
},true);

你必须提出另一个论点(真实),这意味着要深入观察&#39;。这在您观察嵌套对象或对象数组时适用。

你也可以在这里看到。 How to deep watch an array in angularjs?

顺便说一句,没有使用ng-model到div

<div class="badge badge-warning" id="msgCount">{{alerts.length}}</div>

这就够了。

答案 2 :(得分:0)

如果您想在两个控制器之间进行通话,您可以使用$ broadcast或使用服务来存储该值。我更喜欢使用服务,你也可以在其他情况下使用这个'serviceForStoringValue'。

.controller('controller1',function($scope,serviceForStoringValue){
  $scope.getCount = serviceForStoringValue.getCount;
})
 -----------------
.controller('controller2',function($scope,serviceForStoringValue){
  $scope.$watch('',function(n,o){
     serviceForStoringValue.setCount(n.length);
  },true)
})
-----------------
.factory('serviceForStoringValue',function(){
   var count;
   function getCount(){
     return count;
   }
   function setCount(n){
      count = n;
   }

   return {
    getCount:getCount,
    setCount:setCount
   }
 })


<div>{{getCount()}}<div>

答案 3 :(得分:0)

非常感谢KreepN给了我一些指导。我终于意识到模板中的控制器调用是不必要的,因为在主页面上的控制器div内呈现了div。一旦我删除了所有内容落在我的控制器标记内,并且计数按预期工作。