Errore angolare ng-repeat "Non sono consentiti duplicati in un ripetitore."


472

Sto definendo un filtro personalizzato in questo modo:

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

Come puoi vedere ng-repeat in cui viene utilizzato il filtro è nidificato in un'altra ng-repeat

Il filtro è definito in questo modo:

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

Sto ottenendo:

Errore: i duplicati in un ripetitore non sono ammessi. Ripetitore: commento in item.comments | intervallo: 1: 2 ngRepeatAction @ https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

Risposte:


954

La soluzione è effettivamente descritta qui: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

AngularJS non consente duplicati in una direttiva ng-repeat. Questo significa che se stai provando a fare quanto segue, otterrai un errore.

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

Tuttavia, modificando leggermente il codice sopra per definire un indice per determinare l'univocità come di seguito, lo farà funzionare di nuovo.

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

I documenti ufficiali sono qui: https://docs.angularjs.org/error/ngRepeat/dupes


48
Volevo menzionare che è possibile applicare qualsiasi proprietà di tracciamento personalizzata per definire l'unicità, non solo $ index. Poiché in questo scenario gli oggetti non hanno altre proprietà, questo funziona bene. Il motivo per cui si verifica questo errore è che angolare utilizza un dizionario per memorizzare l'id di un elemento come chiave con il valore come riferimento DOM. Dal codice (riga 15402 in angular.js) sembra che stiano memorizzando nella cache elementi DOM precedentemente trovati in base alla loro chiave come ottimizzazione delle prestazioni. Poiché hanno bisogno di chiavi univoche, generano esplicitamente questo errore quando trovano chiavi duplicate sulla riga 15417
devshorts,

16
<div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" >il "filtro di ricerca" deve essere prima di "traccia per $ indice"
Zhe Hu

21
Yikes, che design inutilmente sgradevole da parte di Angular. Sarebbe molto, molto facile perdere questo problema durante lo sviluppo e il test perché l'array non conteneva mai duplicati, solo per far esplodere la tua app in produzione quando viene esposta per la prima volta ai duplicati. Ho già creato app angolari senza conoscere la restrizione "no dupes"; Ora mi ritrovo a pensare indietro e mi chiedo se ho inconsapevolmente creato codice non funzionante.
Mark Amery,

la nostra app è esplosa per questo motivo e non sono uno sviluppatore angolare. La $indexvariabile esiste da qualche parte?
Chang Zhao,

nota che c'è un avvertimento se aggiorni gli elementi dell'array in un secondo momento, non ricompilerà i tag DOM, mostrando invece dati non aggiornati. Puoi usarlo in track by ($index + ':' + row)modo che aggiornerà le singole persone <ng-repeat>ogni volta che vengono aggiornati i suoi dati, così come quando viene aggiunto un nuovo elemento, senza inciampare nei
duplicati

45

Per coloro che si aspettano JSON e continuano a ricevere lo stesso errore, assicurati di analizzare i tuoi dati:

$scope.customers = JSON.parse(data)

4
questo non funziona per me, mi aspetto json, dopo aver utilizzato il servizio $ http, ma SyntaxError: token imprevisto o su Object.parse (nativo)
aurelius

1
@Fergus felice che questo funzioni per te; tuttavia, assicurati di cercare la differenza tra JSON.parse e JSON.stringify se non lo sai già.
utileBee

2
Pazzo. Dopo mesi di corretto funzionamento, Angular ha deciso bruscamente che il JSON restituito da $ http () non era più JSON. L'analisi esplicita ha risolto questo problema per noi. Grazie per il pazzo suggerimento.
Eric L.,

12

Stavo riscontrando un problema nel mio progetto in cui utilizzavo ng-repeat track di $ index ma i prodotti non stavano riflettendo quando i dati provengono dal database. Il mio codice è il seguente:

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

Nel codice sopra, il prodotto è una direttiva separata per visualizzare il prodotto, ma sono venuto a sapere che $ index causa problemi quando passiamo i dati dall'ambito. Pertanto, le perdite di dati e il DOM non possono essere aggiornati.

Ho trovato la soluzione usando product.id come chiave in ng-repeat come di seguito:

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

Ma il codice sopra riportato non riesce e genera l'errore seguente quando più di un prodotto viene fornito con lo stesso ID:

angular.js: 11706 Errore: [ngRepeat: dupes] Non sono consentiti duplicati in un ripetitore. Utilizzare l'espressione "traccia per" per specificare chiavi univoche. Ripetitore

Quindi finalmente ho risolto il problema creando una chiave dinamica unica di ng-repeat come di seguito:

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

Questo ha risolto il mio problema e spero che questo ti possa aiutare in futuro.


1
Sicuramente track by $indexsarebbe meglio di track by (product.id + $index)? Per prima cosa, track by $indexè più semplice, e per un'altra, probabilmente non hai alcuna garanzia che i valori di (product.id + $index)saranno unici. Ad esempio, se l'array inizia con un prodotto con id5 e successivamente c'è un prodotto con id4, i loro valori (product.id + $index)saranno entrambi 5 (5 + 0 per il primo prodotto, 4 + 1 per il secondo) e ancora ottenere i duplicati in un ripetitore non sono ammessi errori.
Mark Amery,

1
Concordo sul fatto che $ index sia più semplice, ma la soluzione di cui sopra funziona per me per risolvere tutti i problemi che stavo affrontando con $ index. E nel mio caso product.id è alfanumerico, quindi (product.id + $ index) non può essere duplicato in nessun caso. Quindi l'idea alla base di questa soluzione era che se $ index sta causando problemi in un caso, allora possiamo usare qualsiasi logica con traccia con cui viene creato l'ID in modo univoco.
Mahima Agrawal,

5

Che cosa intendi fare per il tuo filtro "range"?

Ecco un esempio funzionante di ciò che penso che stai cercando di fare: 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

Se per caso questo errore si verifica quando si lavora con SharePoint 2010: rinominare le estensioni dei file .json e assicurarsi di aggiornare il percorso restService. Non è stato richiesto alcun "traccia per $ indice" aggiuntivo.

Fortunatamente mi è stato inoltrato questo link a questa logica:

.json diventa un tipo di file importante in SP2010. SP2010 include determinati endpoint del servizio Web. Il percorso di questi file è nella cartella 14hive \ isapi. L'estensione di questi file è .json. Questo è il motivo per cui dà un simile errore.

"importa solo che il contenuto di un file json è json, non la sua estensione"

Una volta modificate le estensioni dei file, dovrebbero essere tutte impostate.


0

Nel caso in cui ciò accada a qualcun altro, lo sto documentando qui, ho riscontrato questo errore perché ho impostato erroneamente il modello ng come l'array 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>

Invece di:

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

Ho controllato l'array e non avevo duplicati, ricontrolla solo le tue variabili.


0

I duplicati in un ripetitore non sono ammessi. Utilizzare l'espressione "traccia per" per specificare chiavi univoche.

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

Esempio

<!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
Si prega di dichiarare tutta l'affiliazione a qualsiasi link pubblicato
Draken,

0

Se chiamate un ng-repeat all'interno di un tag <ul>, potreste essere in grado di consentire duplicati. Vedi questo link per riferimento. Vedi Todo2.html


-1

La mia JSONrisposta è stata così:

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

Quindi, lo ng-repeat = "item in variables.items" visualizzavo.


-1

I duplicati in un ripetitore non sono ammessi. Utilizzare l'espressione "traccia per" per specificare chiavi univoche. Ripetitore: sdetail in mydt, chiave duplicata: stringa:, valore duplicato:

Ho riscontrato questo errore perché avevo scritto un nome di database errato nella mia parte php api ......

Pertanto, questo errore può verificarsi anche durante il recupero dei dati dalla base di database, il cui nome è stato scritto in modo errato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.