angularjs指令:$rootScope:infdig错误



我正试图用angularjs 1.2.15:构建一个分页指令

这是我的观点:

<input type="text" ng-model="filter.user">
<input type="number" ng-model="filter.limit" ng-init="filter.limit=5">
<ul>
  <li ng-repeat="user in (filteredUsers = (users | orderBy:order:reverse | filter:filter.user ) | limitTo: filter.limit)" ng-click="showDetails(user)">
    {{user.id}} / {{user.firstname}} {{user.lastname}}
  </li>
</ul>
<div pagination data='filteredUsers' limit='filter.limit'></div>

这是我的分页指令:

app.directive('pagination', function(){
  return {
    restrict: 'A',
    templateUrl: 'partials/pagination.html',
    scope: {
      data: '=data',
      limit: '=limit'
    }
  }
})

没有分页指令,一切都很好。然而,对于我的新指令,只要我加载页面,我就会得到一个$rootScope:infdig错误,我不理解这个错误,因为该指令没有对可能导致无限循环的数据进行任何操作
这里的问题是什么?我该如何解决?谢谢

更新:
这是控制器和资源
控制器:

usersModule.controller('usersController',
  function ($scope, Users) {
    function init(){
      $scope.users = Users.get();
    }
    init();
})

资源(从REST API获取作为数组的用户):

app.factory('Users', function($resource) {
  return $resource('http://myrestapi.tld/users', null,{
       'get': { method:'GET', isArray: true, cache: true }
   });
});

更新2

下面是一个演示:http://plnkr.co/edit/9GCE3Kzf21a7l10GFPmy?p=preview
只需在左侧输入中键入一个字母(例如"f")。

问题不在指令中,而是在指令创建的$watch中。当您将filteredUsers发送到指令时,该指令会创建以下行:

$scope.$watch("filteredUsers", function() {
    // Directive Code...
});

请注意以下示例中我们如何在没有指令的情况下复制它:http://plnkr.co/edit/uRj19PyXkvnLNyh5iY0j

之所以会发生这种情况,是因为每次运行摘要时都会更改filteredUsers(因为您将赋值放在了ng-reeat语句中)。

要解决此问题,您可以考虑在控制器中使用$watch:的额外参数"true"来监视和过滤数组

$scope.$watch("users | orderBy:order:reverse | filter:filter.user", function(newVal) {
    $scope.filteredUsers = newVal;
}, true);

您可以在此处查看解决方案:http://plnkr.co/edit/stxqBtzLsGEXmsrv3Gp6

没有额外参数(true)的$watch将与对象进行简单的比较,并且由于在每个摘要循环中都创建了一个新的数组,因此对象总是不同的。当您将true参数传递给$watch函数时,这意味着它实际上会在再次运行$watch之前与返回的对象进行深入比较,因此即使您有具有相同数据的不同数组实例,它也会认为它们是相等的。

快速解决方案是在指令中添加"手动"$watchCollection,而不是双向绑定。

app.directive('pagination', function($parse){
  return {
    restrict: 'A',
    template: '',
    scope: {
      limit: '=limit'
    },
    link: function(scope, elem, attrs) {
      var dataExpr = $parse(attrs.data);
      var deregister = scope.$parent.$watchCollection(dataExpr, function(val) {
        scope.data = val;
      });
      scope.$on('$destroy', deregister);
    }
  }
})

$watchCollection监视数组的内容,而不是对它的引用

看到它在这里运行。

一般来说,我不喜欢这样的表达:

filteredUsers = (users | orderBy:order:reverse | filter:filter.user )

内部视图。视图应仅呈现$scope属性,而不应创建新属性。

此错误可能会删除以清除设置中的浏览器历史记录。我遇到了同样的问题,并应用了许多解决方案来解决这个问题,但无法解决。但当我删除浏览器历史记录并缓存时,这个问题就解决了。愿这对你有所帮助。

最新更新