Angular ng-repeat Error "Duplikate in einem Repeater sind nicht zulässig."

472

Ich definiere einen benutzerdefinierten Filter wie folgt:

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

Wie Sie sehen können, ist die ng-Wiederholung, in der der Filter verwendet wird, in einer anderen ng-Wiederholung verschachtelt

Der Filter ist wie folgt definiert:

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;
    };
});

Ich erhalte:

Fehler: Duplikate in einem Repeater sind nicht zulässig. Repeater: Kommentar in item.comments | Bereich: 1: 2 ngRepeatAction @ https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

Speisen
quelle

Antworten:

955

Die Lösung wird hier tatsächlich beschrieben: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

AngularJS erlaubt keine Duplikate in einer ng-repeat-Direktive. Dies bedeutet, dass Sie eine Fehlermeldung erhalten, wenn Sie Folgendes versuchen.

// 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]">

Wenn Sie den obigen Code jedoch geringfügig ändern, um einen Index zu definieren, um die Eindeutigkeit wie folgt zu bestimmen, funktioniert er wieder.

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

Offizielle Dokumente finden Sie hier: https://docs.angularjs.org/error/ngRepeat/dupes

Webnet
quelle
48
Ich wollte erwähnen, dass Sie jede benutzerdefinierte Tracking-Eigenschaft anwenden können, um die Eindeutigkeit zu definieren, nicht nur $ index. Da in diesem Szenario die Objekte keine anderen Eigenschaften haben, funktioniert dies einwandfrei. Der Grund für diesen Fehler ist, dass Angular ein Wörterbuch verwendet, um die ID eines Elements als Schlüssel mit dem Wert als DOM-Referenz zu speichern. Aus dem Code (Zeile 15402 in angle.js) geht hervor, dass zuvor gefundene DOM-Elemente basierend auf ihrem Schlüssel als Leistungsoptimierung zwischengespeichert werden. Da sie eindeutige Schlüssel benötigen, werfen sie diesen Fehler explizit aus, wenn sie doppelte Schlüssel in Zeile 15417 finden
devshorts
16
<div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" >Der "Suchfilter" muss vor "Track by $ Index" stehen
Zhe Hu
21
Huch, was für ein sinnlos böses Design von Angular. Es wäre sehr, sehr leicht, dieses Problem während der Entwicklung und des Testens zu übersehen, da Ihr Array niemals Duplikate enthielt, nur um Ihre App in der Produktion explodieren zu lassen, wenn sie zum ersten Mal Dupes ausgesetzt wird. Ich habe bereits Angular-Apps erstellt, ohne über die Einschränkung "Keine Dupes" Bescheid zu wissen. Ich denke jetzt zurück und frage mich, ob ich unwissentlich kaputten Code verfasst habe.
Mark Amery
Unsere App ist aus diesem Grund explodiert und ich bin kein Winkelentwickler. Existiert eine $indexVariable irgendwo?
Chang Zhao
Beachten Sie, dass es eine Einschränkung gibt, wenn Sie Ihre Array-Elemente später aktualisieren. Dadurch werden die DOM-Tags nicht neu kompiliert, sondern veraltete Daten angezeigt. Sie können verwenden, track by ($index + ':' + row)damit es einzelne <ng-repeat>s aktualisiert, wenn seine Daten aktualisiert werden, sowie wenn ein neues Element hinzugefügt wird, ohne über
Dupes zu stolpern
45

Stellen Sie für diejenigen, die JSON erwarten und dennoch denselben Fehler erhalten, sicher, dass Sie Ihre Daten analysieren:

$scope.customers = JSON.parse(data)
nützlichBee
quelle
4
Dies funktioniert nicht für mich, ich erwarte json, nachdem $ http-Dienst verwendet wurde, aber SyntaxError: Unerwartetes Token o bei Object.parse (native)
Aurelius
1
@Fergus froh, dass dies für Sie funktioniert; Achten Sie jedoch auf den Unterschied zwischen JSON.parse und JSON.stringify, sofern Sie dies nicht bereits wissen.
nützlichBee
2
Verrückt. Nach monatelanger korrekter Arbeit entschied Angular abrupt, dass der von $ http () zurückgegebene JSON nicht mehr JSON war. Durch explizites Parsen wurde dieses Problem für uns gelöst. Danke für den verrückten Vorschlag.
Eric L.
12

Ich hatte ein Problem in meinem Projekt, bei dem ich ng-repeat track by $ index verwendete, aber die Produkte wurden nicht reflektiert, wenn Daten aus der Datenbank stammen. Mein Code ist wie folgt:

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

Im obigen Code ist product eine separate Anweisung zum Anzeigen des Produkts. Aber ich habe erfahren, dass $ index Probleme verursacht, wenn wir Daten aus dem Bereich herausgeben. Daher können die Datenverluste und das DOM nicht aktualisiert werden.

Ich habe die Lösung gefunden, indem ich product.id als Schlüssel für ng-repeat wie folgt verwendet habe:

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

Der obige Code schlägt jedoch erneut fehl und löst den folgenden Fehler aus, wenn mehr als ein Produkt dieselbe ID hat:

angle.js: 11706 Fehler: [ngRepeat: dupes] Duplikate in einem Repeater sind nicht zulässig. Verwenden Sie den Ausdruck 'track by', um eindeutige Schlüssel anzugeben. Verstärker

Schließlich habe ich das Problem gelöst, indem ich den dynamischen eindeutigen Schlüssel für ng-repeat wie folgt erstellt habe:

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

Dies hat mein Problem gelöst und hoffe, dass dies Ihnen in Zukunft helfen wird.

Mahima Agrawal
quelle
1
Wäre track by $indexdoch besser als track by (product.id + $index)? Zum einen track by $indexist es einfacher und zum anderen haben Sie wahrscheinlich keine Garantie dafür, dass die Werte von (product.id + $index)eindeutig sind. Wenn Ihr Array beispielsweise mit einem Produkt mit id5 beginnt und danach ein Produkt mit id4, sind die Werte von (product.id + $index)5 (5 + 0 für das erste Produkt, 4 + 1 für das zweite) und Sie Immer noch erhalten die Duplikate in einem Repeater Fehler nicht erlaubt .
Mark Amery
1
Ich bin damit einverstanden, dass $ index einfacher ist, aber die obige Lösung funktioniert für mich, um alle Probleme zu lösen, mit denen ich bei $ index konfrontiert war. Und in meinem Fall ist product.id alphanumerisch, so dass (product.id + $ index) auf keinen Fall dupliziert werden kann. Die Idee hinter dieser Lösung war also, dass wir, wenn $ index in einem Fall ein Problem verursacht, jede Logik mit Spur verwenden können, mit der die ID eindeutig erstellt wird.
Mahima Agrawal
5

Was beabsichtigen Sie mit Ihrem "Bereichs" -Filter zu tun?

Hier ist ein funktionierendes Beispiel dessen, was Sie meiner Meinung nach versuchen: 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'
            ]
        }
    ];
}
Hesekiel Victor
quelle
1

Wenn dieser Fehler zufällig bei der Arbeit mit SharePoint 2010 auftritt: Benennen Sie Ihre .json-Dateierweiterungen um und aktualisieren Sie Ihren restService-Pfad. Es war kein zusätzlicher "Track by $ Index" erforderlich.

Zum Glück wurde mir dieser Link zu dieser Begründung weitergeleitet:

.json wird zu einem wichtigen Dateityp in SP2010. SP2010 enthält bestimmte Webservice-Endpunkte. Der Speicherort dieser Dateien ist der Ordner 14hive \ isapi. Die Erweiterung dieser Dateien lautet .json. Das ist der Grund, warum es einen solchen Fehler gibt.

"kümmert sich nur darum, dass der Inhalt einer JSON-Datei JSON ist - nicht ihre Dateierweiterung"

Sobald die Dateierweiterungen geändert wurden, sollten alle festgelegt werden.

CR Rollyson
quelle
0

Nur für den Fall, dass dies jemand anderem passiert, ich dokumentiere dies hier. Ich habe diesen Fehler erhalten, weil ich das ng-Modell fälschlicherweise genauso eingestellt habe wie das ng-repeat-Array:

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

Anstatt:

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

Ich habe das Array überprüft und hatte keine Duplikate. Überprüfen Sie einfach Ihre Variablen.

Miguel Suarez
quelle
0

Duplikate in einem Repeater sind nicht zulässig. Verwenden Sie den Ausdruck 'track by', um eindeutige Schlüssel anzugeben.

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

Beispiel

<!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>
Yogesh Sharma
quelle
2
Bitte erklären Sie jede Zugehörigkeit zu Links, die Sie posten
Draken
0

Wenn Sie eine ng-Wiederholung innerhalb eines ul-Tags aufrufen, können Sie möglicherweise Duplikate zulassen. Siehe diesen Link als Referenz. Siehe Todo2.html

Das Unbekannte
quelle
-1

Meine JSONAntwort war wie folgt:

{"items": 
  &nbsp;[
    &nbsp;&nbsp;{
      "index": 1,
      "name": "Samantha",
      "rarity": "Scarborough",
      "email": "[email protected]"
    },
    &nbsp;&nbsp;{
      "index": 2,
      "name": "Amanda",
      "rarity": "Vick",
      "email": "[email protected]"
    }]
}

Also habe ich es immer ng-repeat = "item in variables.items" angezeigt.

Jay
quelle
-1

Duplikate in einem Repeater sind nicht zulässig. Verwenden Sie den Ausdruck 'track by', um eindeutige Schlüssel anzugeben. Repeater: sdetail in mydt, Duplicate key: string :, Duplicate value:

Ich bin auf diesen Fehler gestoßen, weil ich in meinem PHP-API-Teil einen falschen Datenbanknamen geschrieben habe ......

Daher kann dieser Fehler auch auftreten, wenn Sie die Daten aus der Datenbankbasis abrufen, deren Name von Ihnen falsch geschrieben wurde.

Vishal Solanki
quelle