Error angular de repetición ng "No se permiten duplicados en un repetidor".

472

Estoy definiendo un filtro personalizado así:

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

Como puede ver, el ng-repeat donde se usa el filtro está anidado dentro de otro ng-repeat

El filtro se define así:

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

Me estoy poniendo:

Error: no se permiten duplicados en un repetidor. Repetidor: comentar en item.comments | rango: 1: 2 ngRepeatAction @ https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

Cenar
fuente

Respuestas:

954

La solución se describe aquí: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

AngularJS no permite duplicados en una directiva ng-repeat. Esto significa que si está intentando hacer lo siguiente, recibirá un error.

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

Sin embargo, cambiar ligeramente el código anterior para definir un índice para determinar la unicidad como se muestra a continuación hará que vuelva a funcionar.

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

Los documentos oficiales están aquí: https://docs.angularjs.org/error/ngRepeat/dupes

Webnet
fuente
48
Quería mencionar que puede aplicar cualquier propiedad de seguimiento personalizada para definir la unicidad, no solo $ index. Como en este escenario los objetos no tienen ninguna otra propiedad, esto funciona bien. La razón por la que ocurre este error es que angular está usando un diccionario para almacenar la identificación de un elemento como la clave con el valor como referencia DOM. Desde el código (línea 15402 en angular.js) parece que están almacenando en caché elementos DOM encontrados previamente en función de su clave como una optimización del rendimiento. Como necesitan claves únicas, arrojan explícitamente este error cuando encuentran claves duplicadas en la línea 15417
devshorts
16
<div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" >el "filtro de búsqueda" debe estar antes de "rastrear por $ index"
Zhe Hu
21
Vaya, qué diseño tan desagradable por parte de Angular. Sería muy, muy fácil pasar por alto este problema durante el desarrollo y las pruebas porque su matriz nunca contuvo duplicados, solo para que su aplicación explote en producción cuando se expone a engaños por primera vez. He creado aplicaciones angulares antes sin saber acerca de la restricción "sin engaños"; Ahora me encuentro pensando y preguntándome si sin saberlo escribí un código roto.
Mark Amery
nuestra aplicación ha explotado debido a esta razón y no soy desarrollador angular. ¿ $indexExiste alguna variable en algún lugar?
Chang Zhao
tenga en cuenta que hay una advertencia si actualiza los elementos de su matriz más tarde, no volverá a compilar las etiquetas DOM, sino que mostrará datos obsoletos. Puede usarlo track by ($index + ':' + row)para actualizar los mensajes individuales <ng-repeat>cada vez que se actualizan sus datos, así como cuando se agrega un nuevo elemento, sin tropezar con
engaños
45

Para aquellos que esperan JSON y siguen obteniendo el mismo error, asegúrese de analizar sus datos:

$scope.customers = JSON.parse(data)
útilBee
fuente
44
esto no funciona para mí, espero json, después de usar el servicio $ http, pero SyntaxError: token inesperado o en Object.parse (nativo)
aurelius
1
@Fergus me alegra que esto funcione para ti; sin embargo, asegúrese de buscar la diferencia entre JSON.parse y JSON.stringify a menos que ya lo sepa.
útilBee
2
Loco. Después de meses de trabajar correctamente, Angular decidió abruptamente que el JSON devuelto por $ http () ya no era JSON. Analizarlo explícitamente resolvió este problema para nosotros. Gracias por la sugerencia loca.
Eric L.
12

Estaba teniendo un problema en mi proyecto en el que estaba usando ng-repeat track por $ index pero los productos no se reflejaban cuando los datos provienen de la base de datos. Mi código es el siguiente:

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

En el código anterior, el producto es una directiva separada para mostrar el producto, pero llegué a saber que $ index causa problemas cuando pasamos los datos del alcance. Por lo tanto, las pérdidas de datos y DOM no se pueden actualizar.

Encontré la solución usando product.id como clave en ng-repeat como a continuación:

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

Pero el código anterior vuelve a fallar y arroja el siguiente error cuando más de un producto viene con la misma identificación:

angular.js: 11706 Error: [ngRepeat: dupes] No se permiten duplicados en un repetidor. Use la expresión 'seguimiento por' para especificar claves únicas. Reloj de repetición

Así que finalmente resolví el problema haciendo una clave dinámica única de ng-repeat como a continuación:

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

Esto resolvió mi problema y espero que esto te ayude en el futuro.

Mahima Agrawal
fuente
1
Seguramente track by $indexsería mejor que track by (product.id + $index)? Por un lado, track by $indexes más simple, y por otro, probablemente no tenga ninguna garantía de que los valores de (product.id + $index)sean únicos. Por ejemplo, si su matriz comienza con un producto con id5 y después de eso hay un producto con id4, sus valores (product.id + $index)serán 5 (5 + 0 para el primer producto, 4 + 1 para el segundo) y obtendrá Todavía obtener los duplicados en un repetidor no se permite error.
Mark Amery
1
Estoy de acuerdo con que $ index es más simple, pero la solución anterior me funcionó para resolver todos los problemas que enfrentaba con $ index. Y en mi caso product.id es alfanumérico, por lo que (product.id + $ index) no puede duplicarse en ningún caso. Entonces, la idea detrás de esta solución era que si $ index está causando algún problema en un caso, entonces podemos usar cualquier lógica con seguimiento por la cual se crea id de forma única.
Mahima Agrawal
5

¿Qué piensa que haga su filtro de "rango"?

Aquí hay una muestra funcional de lo que creo que estás tratando de hacer: 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'
            ]
        }
    ];
}
Ezequiel Victor
fuente
1

Si por casualidad este error ocurre cuando trabaja con SharePoint 2010: cambie el nombre de sus extensiones de archivo .json y asegúrese de actualizar su ruta restService. No se requirió "seguimiento por $ índice" adicional.

Afortunadamente, me enviaron este enlace a esta justificación:

.json se convierte en un tipo de archivo importante en SP2010. SP2010 incluye ciertos puntos finales de servicio web. La ubicación de estos archivos es la carpeta 14hive \ isapi. La extensión de estos archivos es .json. Esa es la razón por la que da tal error.

"solo le importa que el contenido de un archivo json sea json, no su extensión de archivo"

Una vez que se cambian las extensiones de archivo, debe estar todo configurado.

CR Rollyson
fuente
0

En caso de que esto le suceda a alguien más, estoy documentando esto aquí, recibí este error porque configuré por error el modelo ng igual que la matriz 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>

En vez de:

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

Verifiqué la matriz y no tenía duplicados, solo verifique sus variables.

Miguel Suárez
fuente
0

No se permiten duplicados en un repetidor. Use la expresión 'seguimiento por' para especificar claves únicas.

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

Ejemplo

<!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
fuente
2
Declare toda afiliación a los enlaces que publique
Draken,
0

Si llama a ng-repeat dentro de una etiqueta <ul>, puede permitir duplicados. Vea este enlace para referencia. Ver Todo2.html

El desconocido
fuente
-1

Mi JSONrespuesta fue así:

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

Entonces, solía ng-repeat = "item in variables.items" mostrarlo.

Arrendajo
fuente
-1

No se permiten duplicados en un repetidor. Use la expresión 'seguimiento por' para especificar claves únicas. Repetidor: sdetail en mydt, Clave duplicada: cadena:, Valor duplicado:

Me enfrenté a este error porque había escrito un nombre de base de datos incorrecto en mi parte de la API de PHP ...

Por lo tanto, este error también puede ocurrir cuando obtiene los datos de la base de datos, cuyo nombre escribe incorrectamente.

Vishal Solanki
fuente