【问题标题】:"Duplicates in a repeater are not allowed" on ng-repeatng-repeat 上的“不允许在转发器中重复”
【发布时间】:2014-07-27 01:32:26
【问题描述】:

我从服务请求中返回了以下 json 数据:

{
    "entries": [{
        "id": 2081,
        "name": "BM",
        "niceName": "bodmas"
        }]
    }, {
        "id": 8029,
        "name": "Mas",
        "niceName": "Masm"
        }]
    }],
    "count": 2
}

我正在尝试在 html 中使用以下代码来循环访问这些数据:

<option ng-repeat="entry in entries" value="{{entry.name}}">{{entry.name}}</option>

运行代码时出现以下错误:

Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: entry in entries, Duplicate key: string:c

以下是我的控制器的代码:

myApp.controller("MyController", ['$scope', '$http', '$log', function($scope, $http, $log){
       ...

       $http.get('https://myServiceURL').success(function(data){
                    $scope.entries = data;
        });
}]);

有人可以帮我理解为什么会出现这个错误吗?

【问题讨论】:

  • 你不应该在你的控制器中做$scope.entries = data.entries;吗?
  • 您的错误消息似乎不属于您提供的代码的 sn-p。当您的示例显示entry in entries 时,它会提到make in makes。范围内是否有一个名为 makes 的字符串列表?如果是这样,that 就是需要添加 track by 的东西。
  • @MartinAtkins:我尝试使用 makeentries 的条目来简化事情 makes,错误地忘记了修改错误消息。对不起。
  • 您是否尝试添加track by $index而不将其他表达式更改为$index?例如&lt;option ng-repeat="entry in entries track by $index" value="{{entry.name}}"&gt;{{$entry.name}}&lt;/option&gt;

标签: javascript json angularjs for-loop angularjs-ng-repeat


【解决方案1】:

track by $index 添加到您的 ng 重复中,而不是:

<option ng-repeat="entry in entries" value="{{entry.name}}">{{entry.name}}</option>

试试:

<option ng-repeat="entry in entries track by $index" value="{{entry.name}}">{{entry.name}}</option>

关于这方面的更多信息 the documentation for this error message:

在 ngRepeat 表达式中有重复键时发生。 禁止重复键,因为 AngularJS 使用键来关联 DOM 带有项目的节点。

默认情况下,集合是通过引用进行键控的,这对于 最常见的模型,但对于原始类型可能有问题 实习生(分享参考资料)。

【讨论】:

  • 这看起来是一个合理的答案,但可以通过解释为什么这是必要的来改进它,例如什么是“跟踪”以及默认情况下 ng-repeat 所做的事情会搞砸。
  • @martin 我添加了一个指向解释问题的 Angular js 文档的链接。
  • @Malcr001:我试过了,但是value="{{entry.name}}"{{entry.name}} 让我玩空字符串。它们里面没有任何价值。
  • @Malcr001:track by 不是这里的解决方案,因为我在 JSON 数据中没有任何重复的条目。我在调用服务时犯的错误是我将 JSON 响应包装在一个回调函数中,在循环通过 $scope.entries 时导致了问题,并给了我 console.log(data.entries);undefined。谢谢:)
  • @skip 好的,我只是按照控制台中报告的错误消息进行操作。
【解决方案2】:

您的 JSON 无效,应该是:

{
    "entries": [{
        "id": 2081,
        "name": "BM",
        "niceName": "bodmas"
    }, {
        "id": 8029,
        "name": "Mas",
        "niceName": "Masm"
    }],
    "count": 2
}

另外,请确保您在正确的级别访问文档,使用:

$http.get('https://myServiceURL').success(function(data){
    $scope.entries = data.entries;
});

然后,它应该可以工作。看到这个JSBin

【讨论】:

  • 您在评论中使用$scope.entries = data.entries; 说得很对。我在调用该服务时犯的错误是我将 JSON 响应包装在一个回调函数中,该回调函数在循环 $scope.entries 时导致了问题,并给了我 console.log(data.entries);undefined。谢谢:)
  • 同样,我有一个带有 json_encoded 数据的 PHP 响应;在 javascript 中,我忘记了 JSON.parse() 对象,......它工作了一段时间,直到返回数据变得更复杂。
【解决方案3】:

如果我可以添加一个额外的原因来解释为什么会发生这种情况......

如果您使用 JS 对象 [] 或 {}

你将它传递给这样的指令

<my-directive my-attribute="{{ myObject }}"></my-directive>

在指令中,您必须通过这样做将 myObject 变回对象

...
controller: function( $scope ){

  $scope.links = $scope.$eval( $scope.myObject );
....

然后 HTML 和 ng-repeat 将起作用

...
<span class="" ng-repeat="link in links">
...

ngRepeat 不知道如何重复单个字符串。

这是对象在 $scope.$eval 之前的样子

"[{ hello: 'you' }]"

$scope.$eval() 之后

[{ hello: 'you' }] an actual object to repeat over.

错误类型会引用它不能重复的字符串。这是我得到的错误。

错误:[ngRepeat:dupes]http://errors.angularjs.org/1.3.0-beta.8/ngRepeat/dupes?p0=link%20in%20links&p1=string%3Al

【讨论】:

  • 这解决了我花了几个小时解决的问题。谢谢
【解决方案4】:

您的作用域中的数据结构似乎存在问题。您的示例 JSON 显示了一个具有 entries 属性和 count 属性的对象。然后,您将整个对象作为entries 放在您的范围内。这意味着您需要以entries.entries 的身份访问条目,计数为entries.count。也许这个控制器更接近你想要的:

myApp.controller("MyController", ['$scope', '$http', '$log', function($scope, $http, $log){
    ...

    $http.get('https://myServiceURL').success(function(data){
        $scope.entries = data.entries;
        $scope.count = data.count;
    });
}]);

【讨论】:

  • 仔细看,这并不能真正解释给定的错误,因为它会尝试遍历字符串“entries”和“count”;我认为这里可能还有其他一些在给出的示例中不明显的事情,因为如果你的数组是像string 这样的原始类型,你应该只需要track by
  • 这也是我的提议,但我意识到这与他的错误并没有真正的联系。它只是按原样修复了示例。
  • @MartinAtkins 和 @Goodzilla:是的,记录 data.entriesdata.count 结果都给了我undefined
  • @MartinAtkins:是的,这是正确的。我在调用服务时犯的错误是我将 JSON 响应包装在一个回调函数中,在循环通过 $scope.entries 时导致问题并给我undefined for console.log(data.entries);。我只能接受一个答案,而且因为 Goodzilla 首先想通了,所以我接受了他的答案。请不要介意。你同样乐于助人。谢谢你:)
【解决方案5】:

// 要允许使用 ASP.NET AJAX 从脚本调用此 Web 服务,请取消注释以下行。

[System.Web.Script.Services.ScriptService] ==> 如果您使用 .NET 服务,请取消注释此行

【讨论】:

    【解决方案6】:

    In ng-repeat 中的重复是不允许的。 示例

        <!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>
    

    【讨论】:

    • 您能否将您的答案(现在是一年前在讨论最初进行之后)与另一个已接受的答案联系起来。为什么它会增加价值,如果可能“世界改变了”,并且可能接受的答案不再起作用或沿着这些思路起作用。谢谢。
    猜你喜欢
    • 2021-12-26
    • 2015-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    相关资源
    最近更新 更多