【问题标题】:Angular ng-repeat Error "Duplicates in a repeater are not allowed."Angular ng-repeat 错误“不允许在转发器中重复。”
【发布时间】:2021-12-26 17:38:09
【问题描述】:

我正在定义一个自定义过滤器,如下所示:

<div class="idea item" ng-repeat="item in items" isoatom>    
    <div class="section comment clearfix" ng-repeat="comment in item.comments | range:1:2">
        ....
    </div>
</div>

如您所见,正在使用过滤器的 ng-repeat 嵌套在另一个 ng-repeat 中

过滤器是这样定义的:

myapp.filter('range', function() {
    return function(input, min, max) {
        min = parseInt(min); //Make string input int
        max = parseInt(max);
        for (var i=min; i<max; i++)
            input.push(i);
        return input;
    };
});

我明白了:

错误:不允许在转发器中重复。中继器:item.cmets 中的注释 |范围:1:2 ngRepeatAction@https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

【问题讨论】:

    标签: angularjs ng-repeat


    【解决方案1】:

    解决方案其实在这里描述:http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

    AngularJS 不允许在 ng-repeat 指令中重复。这意味着如果您尝试执行以下操作,您将收到错误消息。

    // This code throws the error "Duplicates in a repeater are not allowed.
    // Repeater: row in [1,1,1] key: number:1"
    <div ng-repeat="row in [1,1,1]">
    

    但是,稍微更改上面的代码来定义一个索引来确定唯一性,如下所示,它将使它再次工作。

    // This will work
    <div ng-repeat="row in [1,1,1] track by $index">
    

    官方文档在这里:https://docs.angularjs.org/error/ngRepeat/dupes

    【讨论】:

    • 我想提一下,您可以应用任何自定义跟踪属性来定义唯一性,而不仅仅是 $index。由于在这种情况下,对象没有任何其他属性,因此可以正常工作。发生此错误的原因是 Angular 使用字典将项目的 id 存储为键,值作为 DOM 引用。从代码(angular.js 中的第 15402 行)来看,它们似乎在缓存以前找到的 DOM 元素,基于它们的键作为性能优化。由于他们需要唯一键,因此当他们在第 15417 行发现重复键时会显式抛出此错误
    • &lt;div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" &gt;“搜索过滤器”需要在“track by $index”之前
    • 哎呀,Angular 的设计真是毫无意义。在开发和测试期间很容易错过这个问题,因为您的数组从不包含重复项,只会在您的应用程序第一次暴露于重复项时在生产中爆炸。我以前构建过 Angular 应用程序,但不知道“没有欺骗”的限制;我现在发现自己回想起来,想知道我是否在不知不觉中编写了损坏的代码。
    • 如果数组项是对象,是什么让每个项都是唯一的?
    • @Shlomi Gotcha。请注意track by $index 有一些big pitfalls
    【解决方案2】:

    对于那些期待 JSON 并且仍然遇到相同错误的人,请确保您解析数据:

    $scope.customers = JSON.parse(data)
    

    【讨论】:

    • 这对我不起作用,我希望 json,在使用 $http 服务后,但是 SyntaxError: Unexpected token o at Object.parse (native)
    • @Fergus 很高兴这对你有用;但是,除非您已经知道,否则请务必查找 JSON.parse 和 JSON.stringify 之间的区别。
    • 疯了。经过几个月的正常工作,Angular 突然决定从 $http() 返回的 JSON 不再是 JSON。显式解析它为我们解决了这个问题。感谢您的疯狂建议。
    【解决方案3】:

    我在项目中遇到问题,我使用 $index 的 ng-repeat 跟踪,但当数据来自数据库时,产品没有得到反映。我的代码如下:

    <div ng-repeat="product in productList.productList track by $index">
      <product info="product"></product>
     </div>
    

    在上面的代码中,product 是一个单独的指令来显示产品。但是我知道 $index 在我们将数据从范围中传递出去时会导致问题。所以数据丢失和DOM无法更新。

    我通过使用 product.id 作为 ng-repeat 中的键找到了解决方案,如下所示:

    <div ng-repeat="product in productList.productList track by product.id">
      <product info="product"></product>
     </div>
    

    但是当多个产品具有相同的 id 时,上述代码再次失败并引发以下错误:

    angular.js:11706 错误:[ngRepeat:dupes] 不允许在转发器中重复。使用“track by”表达式指定唯一键。中继器

    所以最后我通过制作 ng-repeat 的动态唯一键解决了这个问题,如下所示:

    <div ng-repeat="product in productList.productList track by (product.id + $index)">
      <product info="product"></product>
     </div>
    

    这解决了我的问题,希望这对您将来有所帮助。

    【讨论】:

    • 肯定track by $index 会比track by (product.id + $index) 更好?一方面,track by $index 更简单,另一方面,您实际上可能无法保证(product.id + $index) 的值是唯一的。例如,如果您的数组以 id 为 5 的产品开头,然后有一个 id 为 4 的产品,则它们的 (product.id + $index) 的值都将为 5(第一个产品为 5+0,4+ 1 为第二个),你会仍然得到 Duplicates in a repeater are not allowed 错误。
    • 我同意 $index 更简单,但上述解决方案对我来说可以解决我在 $index 中遇到的所有问题。在我的例子中 product.id 是字母数字所以 (product.id + $index) 在任何情况下都不能重复。所以这个解决方案背后的想法是,如果 $index 在一个案例中引起任何问题,那么我们可以使用任何带有唯一创建 id 的跟踪的逻辑。
    【解决方案4】:

    你打算用你的“范围”过滤器做什么?

    这是我认为您正在尝试做的工作示例:http://jsfiddle.net/evictor/hz4Ep/

    HTML:

    <div ng-app="manyminds" ng-controller="MainCtrl">
      <div class="idea item" ng-repeat="item in items" isoatom>    
        Item {{$index}}
        <div class="section comment clearfix" ng-repeat="comment in item.comments | range:1:2">
          Comment {{$index}}
          {{comment}}
        </div>
      </div>
    </div>
    

    JS:

    angular.module('manyminds', [], function() {}).filter('range', function() {
        return function(input, min, max) {
            var range = [];
            min = parseInt(min); //Make string input int
            max = parseInt(max);
            for (var i=min; i<=max; i++)
                input[i] && range.push(input[i]);
            return range;
        };
    });
    
    function MainCtrl($scope)
    {
        $scope.items = [
            {
                comments: [
                    'comment 0 in item 0',
                    'comment 1 in item 0'
                ]
            },
            {
                comments: [
                    'comment 0 in item 1',
                    'comment 1 in item 1',
                    'comment 2 in item 1',
                    'comment 3 in item 1'
                ]
            }
        ];
    }
    

    【讨论】:

      【解决方案5】:

      如果在使用 SharePoint 2010 时偶然发生此错误:重命名您的 .json 文件扩展名并确保更新您的 restService 路径。不需要额外的“按 $index 跟踪”。

      幸运的是,我将此link 转发给了这个理由:

      .json 成为 SP2010 中重要的文件类型。 SP2010 包括某些 Web 服务端点。这些文件的位置是 14hive\isapi 文件夹。这些文件的扩展名为 .json。这就是它给出这样一个错误的原因。

      “只关心 json 文件的内容是 json - 而不是它的文件扩展名”

      文件扩展名一旦改变,就应该全部设置好了。

      【讨论】:

        【解决方案6】:

        以防万一这发生在其他人身上,我在此记录,我收到此错误是因为我错误地将 ng-model 设置为与 ng-repeat 数组相同:

         <select ng-model="list_views">
             <option ng-selected="{{view == config.list_view}}"
                 ng-repeat="view in list_views"
                 value="{{view}}">
                 {{view}}
             </option>
         </select>
        

        代替:

        <select ng-model="config.list_view">
             <option ng-selected="{{view == config.list_view}}"
                 ng-repeat="view in list_views"
                 value="{{view}}">
                 {{view}}
             </option>
         </select>
        

        我检查了数组,没有任何重复,只需仔细检查您的变量。

        【讨论】:

          【解决方案7】:

          不允许在转发器中重复。使用“track by”表达式指定唯一键。

          Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}
          

          例子

          <!DOCTYPE html>
          <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
          <head>
              <meta charset="utf-8" />
              <title></title>
              <script src="angular.js"></script>
          
          </head>
          <body>
              <div ng-app="myApp" ng-controller="personController">
                  <table>
                      <tr> <th>First Name</th> <th>Last Name</th> </tr>
                      <tr ng-repeat="person in people track by $index">
                          <td>{{person.firstName}}</td>
                          <td>{{person.lastName}}</td>
                          <td><input type="button" value="Select" ng-click="showDetails($index)" /></td>
                      </tr>
          
                  </table> <hr />
                  <table>
                      <tr ng-repeat="person1 in items track by $index">
                          <td>{{person1.firstName}}</td>
                          <td>{{person1.lastName}}</td>
                      </tr>
                  </table>
                  <span>   {{sayHello()}}</span>
              </div>
              <script> var myApp = angular.module("myApp", []);
                  myApp.controller("personController", ['$scope', function ($scope)
                  { 
                      $scope.people = [{ firstName: "F1", lastName: "L1" },
                          { firstName: "F2", lastName: "L2" }, 
                          { firstName: "F3", lastName: "L3" }, 
                          { firstName: "F4", lastName: "L4" }, 
                          { firstName: "F5", lastName: "L5" }]
                      $scope.items = [];
                      $scope.selectedPerson = $scope.people[0];
                      $scope.showDetails = function (ind) 
                      { 
                          $scope.selectedPerson = $scope.people[ind];
                          $scope.items.push($scope.selectedPerson);
                      }
                      $scope.sayHello = function ()
                      {
                          return $scope.items.firstName;
                      }
                  }]) </script>
          </body>
          </html>
          

          【讨论】:

          • 请声明与您发布的任何链接的所有从属关系
          【解决方案8】:

          如果您在

            标记内调用 ng-repeat,则可以允许重复。请参阅此链接以供参考。 See Todo2.html

          【讨论】:

            【解决方案9】:

            我的JSON 回复是这样的:

            {"items": 
              &nbsp;[
                &nbsp;&nbsp;{
                  "index": 1,
                  "name": "Samantha",
                  "rarity": "Scarborough",
                  "email": "maureen@sykes.mk"
                },
                &nbsp;&nbsp;{
                  "index": 2,
                  "name": "Amanda",
                  "rarity": "Vick",
                  "email": "jessica@livingston.mv"
                }]
            }
            

            所以,我使用ng-repeat = "item in variables.items" 来显示它。

            【讨论】:

              【解决方案10】:

              不允许在转发器中重复。使用“track by”表达式指定唯一键。中继器:mydt 中的 sdetail,重复键:字符串:,重复值:

              我遇到了这个错误,因为我在我的 php api 部分中写了错误的数据库名称......

              所以当你从数据库中取数据时也可能出现这个错误,数据库的名字你写的不正确。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-10-20
                • 1970-01-01
                • 2017-03-25
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多