Błąd kątowy powtórzenia ng „Duplikaty w repeaterze nie są dozwolone”.


472

Definiuję niestandardowy filtr tak:

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

Jak widać, powtórzenie ng, w którym używany jest filtr, jest zagnieżdżone w innym powtórzeniu ng

Filtr jest zdefiniowany w następujący sposób:

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

Dostaję:

Błąd: duplikaty w repeaterze są niedozwolone. Repeater: komentarz w item.comments | zakres: 1: 2 ngRepeatAction @ https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

Odpowiedzi:


955

Rozwiązanie jest faktycznie opisane tutaj: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

AngularJS nie zezwala na duplikaty w dyrektywie powtórzenia ng. Oznacza to, że jeśli próbujesz wykonać następujące czynności, pojawi się błąd.

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

Jednak nieznaczna zmiana powyższego kodu w celu zdefiniowania indeksu w celu ustalenia unikatowości, jak poniżej, spowoduje jego ponowne uruchomienie.

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

Oficjalne dokumenty są tutaj: https://docs.angularjs.org/error/ngRepeat/dupes


48
Chciałem wspomnieć, że możesz zastosować dowolną niestandardową właściwość śledzenia, aby zdefiniować unikalność, a nie tylko indeks $. Ponieważ w tym scenariuszu obiekty nie mają żadnych innych właściwości, działa to dobrze. Przyczyną tego błędu jest to, że kąt używa słownika do przechowywania identyfikatora elementu jako klucza z wartością jako odwołanie do DOM. Z kodu (wiersz 15402 w angular.js) wygląda na to, że buforują wcześniej znalezione elementy DOM na podstawie ich klucza jako optymalizacji wydajności. Ponieważ potrzebują unikalnych kluczy, jawnie rzucają ten błąd, gdy znajdują duplikaty kluczy w linii 15417
devshorts

16
<div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" >„filtr wyszukiwania” musi być wcześniejszy niż „śledź według indeksu $”
Zhe Hu

21
Yikes, jaki bezsensownie paskudny projekt ze strony Angulara. Bardzo łatwo byłoby przeoczyć ten problem podczas programowania i testowania, ponieważ tablica nigdy nie zawierała duplikatów, tylko po to, aby Twoja aplikacja eksplodowała podczas produkcji, gdy zostanie po raz pierwszy narażona na duplikaty. Wcześniej tworzyłem aplikacje Angular, nie wiedząc o ograniczeniu „bez duplikatów”; Teraz myślę o tym i zastanawiam się, czy nieświadomie stworzyłem uszkodzony kod.
Mark Amery

nasza aplikacja eksplodowała z tego powodu i nie jestem programistą kątowym, czy $indexzmienna istnieje gdzieś?
Chang Zhao

Uwaga: jeśli później zaktualizujesz elementy tablicy, nie zostanie ponownie skompilowana znacznik DOM, a zamiast tego pojawią się nieaktualne dane. Możesz użyć track by ($index + ':' + row)tej opcji, aby aktualizować poszczególne <ng-repeat>s przy każdej aktualizacji danych, a także po dodaniu nowego elementu, bez potykania się o duplikaty
Hashbrown

45

Dla tych, którzy oczekują JSON i nadal pojawia się ten sam błąd, upewnij się, że parsujesz swoje dane:

$scope.customers = JSON.parse(data)

4
to nie działa dla mnie, oczekuję json, po użyciu usługi $ http, ale SyntaxError: Nieoczekiwany token o w Object.parse (natywny)
aurelius

1
@Fergus cieszę się, że to działa dla ciebie; Pamiętaj jednak, aby poszukać różnic między JSON.parse i JSON.stringify, chyba że już wiesz.
Przydatne,

2
Zwariowany. Po miesiącach poprawnej pracy, Angular nagle stwierdził, że JSON powrócił z $ http () nie jest już JSON. Wyraźna analiza tego rozwiązania rozwiązała dla nas ten problem. Dzięki za szaloną sugestię.
Eric L.,

12

Miałem problem w moim projekcie, w którym korzystałem ze śledzenia powtórzeń ng według $ index, ale produkty nie były odzwierciedlane, gdy dane pochodziły z bazy danych. Mój kod jest jak poniżej:

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

W powyższym kodzie produkt jest osobną dyrektywą do wyświetlania produktu, ale dowiedziałem się, że $ index powoduje problem, gdy przekazujemy dane z zakresu. Dlatego utrata danych i DOM nie mogą być aktualizowane.

Znalazłem rozwiązanie, używając product.id jako klucza w powtórzeniu ng, jak poniżej:

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

Ale powyższy kod ponownie nie powiedzie się i zgłasza poniższy błąd, gdy więcej niż jeden produkt ma ten sam identyfikator:

angular.js: 11706 Błąd: [ngRepeat: dupes] Duplikaty w repeaterze są niedozwolone. Użyj wyrażenia „śledź według”, aby określić unikalne klucze. Przekaźnik

W końcu rozwiązałem problem, tworząc dynamiczny unikalny klucz powtórzenia ng, jak poniżej:

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

To rozwiązało mój problem i mam nadzieję, że pomoże ci to w przyszłości.


1
Z pewnością track by $indexbyłoby lepiej niż track by (product.id + $index)? Z jednej strony track by $indexjest prostsze, a z drugiej strony prawdopodobnie nie masz żadnej gwarancji, że wartości (product.id + $index)będą unikalne. Na przykład, jeśli twoja tablica zaczyna się od produktu z id5, a potem jest produkt z id4, ich wartości (product.id + $index)będą wynosić 5 (5 + 0 dla pierwszego produktu, 4 + 1 dla drugiego), a ty nadal uzyskać duplikaty w repeaterze nie są dozwolone błąd.
Mark Amery

1
Zgadzam się z tym, że $ index jest prostszy, ale powyższe rozwiązanie działa dla mnie, aby rozwiązać wszystkie problemy, z którymi miałem do czynienia przy pomocy $ index. W moim przypadku product.id jest alfanumeryczny, więc (product.id + $ index) nie można w żadnym wypadku powielić. Ideą tego rozwiązania było więc to, że jeśli $ index powoduje jakiś problem w sprawie, możemy użyć dowolnej logiki ze śledzeniem, dzięki któremu identyfikator jest tworzony w unikalny sposób.
Mahima Agrawal

5

Co zamierzasz zrobić z filtrem „zasięgu”?

Oto działająca próbka tego, co myślę, że próbujesz zrobić: 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'
            ]
        }
    ];
}

1

Jeśli przez przypadek ten błąd wystąpi podczas pracy z programem SharePoint 2010: Zmień nazwy rozszerzeń plików .json i zaktualizuj ścieżkę restService. Nie było wymagane dodatkowe „śledzenie według $ index”.

Na szczęście przekazano mi ten link do tego uzasadnienia:

.json staje się ważnym typem pliku w SP2010. Dodatek SP2010 zawiera punkty końcowe usług sieciowych. Lokalizacja tych plików to folder 14hive \ isapi. Rozszerzenie tych plików to .json. Właśnie dlatego daje taki błąd.

„obchodzi tylko to, że zawartość pliku json to json - a nie jego rozszerzenie”

Po zmianie rozszerzeń plików należy wszystko ustawić.


0

Na wypadek, gdyby stało się to komuś innemu, dokumentuję to tutaj, otrzymywałem ten błąd, ponieważ przez pomyłkę ustawiłem model ng tak samo jak tablicę 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>

Zamiast:

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

Sprawdziłem tablicę i nie miałem żadnych duplikatów, po prostu dwukrotnie sprawdź zmienne.


0

Duplikaty w repeaterze nie są dozwolone. Użyj wyrażenia „śledź według”, aby określić unikalne klucze.

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

Przykład

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

2
Proszę zadeklarować wszelką przynależność do wszelkich zamieszczanych linków
Draken


-1

Moja JSONodpowiedź była taka:

{"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"
    }]
}

Więc kiedyś ng-repeat = "item in variables.items" to wyświetlałem.


-1

Duplikaty w repeaterze nie są dozwolone. Użyj wyrażenia „śledź według”, aby określić unikalne klucze. Repeater: sdetail in mydt, Duplikat klucza: string:, Duplikat wartości:

Napotkałem ten błąd, ponieważ napisałem niepoprawną nazwę bazy danych w części php api ......

Ten błąd może więc wystąpić również podczas pobierania danych z bazy danych, której nazwa została wpisana przez Ciebie niepoprawnie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.