ng-repeat函数以创建新对象并避免[$rootScope:infdig]



>plunker preview
我有一个主数组,其中包含有关用户的信息。
每个项目(用户)都有"数据"数组:

{
  name: 'Linda',
  data: [
    {
      value: 3
    },
    {
      value: 6
    }
  ]
}

我需要像这样打印主数组:

  • 琳达 - 3
  • 琳达 - 6

更新:我可以更改输入中的名称。请参阅版本 2。


所以我使用 ng-repeat with 函数来返回新对象。我得到已知的错误: [$rootScope:infdig]

为了避免此错误,我使用谷歌组方法:"更改"过滤器和"链接器"工厂。
(我想使用$hashKey美元的方法。但我不明白该怎么做)

要获得此错误,请打开我的代码并删除 HTML 中的"更改"过滤器。

问题:也许您知道打印阵列的更简单的解决方案吗?谢谢。
如果我会在打印前排序?

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
  $scope.users = [
    {
      name: 'Linda',
      data: [
        {
          value: 3
        },
        {
          value: 6
        }
      ]
    },
    {
      name: 'John',
      data: [
        {
          value: 2
        },
        {
          value: 11
        }
      ]
    }
  ];
  $scope.getUsersData = function(){
    var output = [];
    $scope.users.forEach(function(user){
      if ('data' in user) {
        user.data.forEach(function(userData){
          output.push({name: user.name, value: userData.value});
        });
      }
    });
    return output;
  };
});
// From https://groups.google.com/d/msg/angular/IEIQok-YkpU/iDw32-YRr3QJ
app.filter('change', function(linker) {
   return function(items) {
      var collection = items.map(function (item) {
        return item;
      });
      return linker(collection, 'some-key');
    };
});
app.factory('linker', function () {
  var links = {};
  return function (arr, key) {
    var link = links[key] || [];
    arr.forEach(function (newItem, index) {
      var oldItem = link[index];
      if (!angular.equals(oldItem, newItem))
        link[index] = newItem;
    });
    link.length = arr.length;
    return links[key] = link;
  }
})
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
    <body ng-app="plunker" ng-controller="MainCtrl as main">
    <ul>
      <li ng-repeat="user in users = getUsersData() | change track by $index">{{user.name}} - {{user.value}}</li>
    </ul>
    <hr>
    <div ng-repeat="user in users">
     <input ng-model="user.name"/>
    </div>
    </body>

尝试这样的事情。 不带过滤器或嵌套 ng-重复

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
  var users = [{
    name: 'Linda',
    data: [{
      value: 3
    }, {
      value: 6
    }]
  }, {
    name: 'John',
    data: [{
      value: 2
    }, {
      value: 11
    }]
  }];
  $scope.getUsersData = function() {
    var output = [];
    users.forEach(function(user, ind) {
      if ('data' in user) {
        user.data.forEach(function(userData, ind) {
          output.push({
            name: user.name,
            value: userData.value
          });
        });
      }
    });
    return output;
  };
  $scope.userFetchedData = $scope.getUsersData(); // here is the magic
});

app.factory('linker', function() {
  var links = {};
  return function(arr, key) {
    var link = links[key] || [];
    arr.forEach(function(newItem, index) {
      var oldItem = link[index];
      if (!angular.equals(oldItem, newItem))
        link[index] = newItem;
    });
    link.length = arr.length;
    return links[key] = link;
  }
})
<!DOCTYPE html>
<html ng-app="plunker">
<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
</head>
<body ng-controller="MainCtrl">
  <ul>
    <li ng-repeat="user in userFetchedData track by $index">{{user.name}} - {{user.value}}</li>
  </ul>
</body>
</html>

如果使用 track by,Angular 不会向数组中的对象添加 $$hashKey 属性。 $$hashKey 是 angular 添加的默认属性,用于继续跟踪给定数组中的更改。使用不带track by ng-repeat来使用 hashKey

plunker 版本 3
我需要更改输入字段中的用户名。所以我认为对我来说简单快捷的解决方案是使用$watch

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
  $scope.users = [
    {
      name: 'Linda',
      data: [
        {
          value: 3
        },
        {
          value: 6
        }
      ]
    },
    {
      name: 'John',
      data: [
        {
          value: 2
        },
        {
          value: 11
        }
      ]
    }
  ];
  
  $scope.$watch(function(){
    return JSON.stringify($scope.users);
  }, function(){
    $scope.usersData = $scope.prepareUsersForPrint($scope.users);
  })
  $scope.prepareUsersForPrint = function(arr){
    var output = [];
    arr.forEach(function(user){
      if ('data' in user) {
        user.data.forEach(function(userData){
          output.push({name: user.name, value: userData.value});
        });
      }
    });
    return output;
  };
});
 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
    <body ng-app="plunker" ng-controller="MainCtrl as main">
    <ul>
      <li ng-repeat="user in usersData track by $index">{{user.name}} - {{user.value}}</li>
    </ul>
    <hr>
    <div ng-repeat="user in users">
      <input ng-model="user.name"/>
    </div>
    </body>

最新更新