Erro angular de repetição ng “Duplicatas em um repetidor não são permitidas.”

472

Estou definindo um filtro personalizado da seguinte forma:

<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 você pode ver, o ng-repeat em que o filtro está sendo usado está aninhado em outro ng-repeat

O filtro é definido assim:

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

Estou entendendo:

Erro: duplicatas em um repetidor não são permitidas. Repetidor: comentário em item.comments | range: 1: 2 ngRepeatAction @ https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

Jantar
fonte

Respostas:

955

A solução é realmente descrita aqui: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

O AngularJS não permite duplicatas em uma diretiva ng-repeat. Isso significa que se você estiver tentando fazer o seguinte, receberá um erro.

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

No entanto, alterar ligeiramente o código acima para definir um índice para determinar a exclusividade, conforme abaixo, fará com que ele funcione novamente.

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

Os documentos oficiais estão aqui: https://docs.angularjs.org/error/ngRepeat/dupes

Webnet
fonte
48
Queria mencionar que você pode aplicar qualquer propriedade de rastreamento personalizado para definir exclusividade, não apenas $ index. Como nesse cenário os objetos não têm outras propriedades, isso funciona bem. A razão pela qual esse erro ocorre é que angular está usando um dicionário para armazenar o ID de um item como chave e o valor como referência DOM. A partir do código (linha 15402 em angular.js), parece que eles estão armazenando em cache elementos DOM encontrados anteriormente com base em sua chave como uma otimização de desempenho. Uma vez que eles precisam de chaves únicas que explicitamente lançar este erro quando encontrar chaves duplicadas na linha 15417
devshorts
16
<div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" >as necessidades "filtros de busca" ser antes "track por $ index"
Zhe Hu
21
Caramba, que design inútil por parte da Angular. Seria muito, muito fácil perder esse problema durante o desenvolvimento e o teste, porque sua matriz nunca continha duplicatas, apenas para que seu aplicativo explodisse em produção quando exposto a dupes pela primeira vez. Eu criei aplicativos Angular antes sem saber sobre a restrição "no dupes"; Agora me pego pensando e me perguntando se criei um código quebrado sem saber.
Mark Amery
nosso aplicativo explodiu por esse motivo e não sou desenvolvedor angular. A $indexvariável existe em algum lugar?
Chang Zhao
observe que há uma ressalva se você atualizar os elementos da matriz posteriormente, eles não recompilarão as tags DOM, mostrando dados obsoletos. Você pode usar track by ($index + ':' + row)para que ele irá atualizar individuais <ng-repeat>s sempre que seus dados atualizados, bem como quando um novo elemento é adicionado, sem tropeçar em dupes
Hashbrown
45

Para quem espera JSON e ainda recebe o mesmo erro, analise seus dados:

$scope.customers = JSON.parse(data)
usefulBee
fonte
4
isso não funciona para mim, espero json, depois de usar $ http serviço, mas SyntaxError: o símbolo inesperado em Object.parse (nativo)
aurelius
1
@Fergus feliz que isso funcione para você; no entanto, verifique a diferença entre JSON.parse e JSON.stringify, a menos que você já saiba.
usar o seguinte código
2
Louco. Após meses trabalhando corretamente, o Angular decidiu abruptamente que o JSON retornado de um $ http () não era mais o JSON. A análise explícita resolveu esse problema para nós. Obrigado pela sugestão maluca.
Eric L.
12

Eu estava com um problema no meu projeto em que usava a faixa ng-repeat por $ index, mas os produtos não estavam refletindo quando os dados vieram do banco de dados. Meu código é como abaixo:

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

No código acima, product é uma diretiva separada para exibir o produto. Mas vim a saber que $ index causa problemas quando passamos os dados para fora do escopo. Portanto, as perdas de dados e o DOM não podem ser atualizados.

Encontrei a solução usando product.id como uma chave no ng-repeat, como abaixo:

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

Mas o código acima falha novamente e gera o erro abaixo quando mais de um produto vem com o mesmo ID:

angular.js: 11706 Erro: [ngRepeat: dupes] Duplicatas em um repetidor não são permitidas. Use a expressão 'rastrear por' para especificar chaves exclusivas. Repetidor

Então, finalmente, resolvi o problema, criando uma chave dinâmica única de repetição de ng, como abaixo:

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

Isso resolveu meu problema e espero que isso ajude você no futuro.

Mahima Agrawal
fonte
1
Certamente track by $indexseria melhor do que track by (product.id + $index)? Por um lado, track by $indexé mais simples e, por outro, você provavelmente não tem realmente nenhuma garantia de que os valores de (product.id + $index)serão únicos. Por exemplo, se sua matriz começar com um produto com id5 e depois houver um produto com id4, os valores de (product.id + $index)ambos serão 5 (5 + 0 para o primeiro produto, 4 + 1 para o segundo) e você ainda obter as duplicatas em um repetidor não são permitidos erros.
Mark # Amery #
1
Concordo que o $ index seja mais simples, mas a solução acima foi trabalhada para resolver todos os problemas que eu estava enfrentando com o $ index. E, no meu caso, product.id é alfanumérico, portanto (product.id + $ index) não pode ser duplicado em nenhum caso. Portanto, a idéia por trás dessa solução era que, se $ index estiver causando algum problema em um caso, poderemos usar qualquer lógica com a faixa pela qual o ID é criado exclusivamente.
Mahima Agrawal
5

O que você pretende fazer com o filtro "intervalo"?

Aqui está uma amostra do que eu acho que você está tentando fazer: 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'
            ]
        }
    ];
}
Ezekiel Victor
fonte
1

Se, por acaso, esse erro ocorrer ao trabalhar com o SharePoint 2010: Renomeie as extensões de arquivo .json e atualize o caminho restService. Nenhuma "faixa por $ index" adicional foi necessária.

Felizmente, eu fui encaminhado este link para esta lógica:

.json se torna um tipo de arquivo importante no SP2010. O SP2010 inclui determinados pontos finais do serviço da web. O local desses arquivos é a pasta 14hive \ isapi. A extensão desses arquivos é .json. Essa é a razão que dá esse erro.

"se importa apenas que o conteúdo de um arquivo json seja json - não sua extensão"

Depois que as extensões do arquivo forem alteradas, tudo estará definido.

CR Rollyson
fonte
0

Caso isso aconteça com outra pessoa, estou documentando isso aqui, estava recebendo esse erro porque, por engano, defino o modelo ng da mesma forma que a 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>

Ao invés 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>

Eu verifiquei o array e não tinha duplicatas, apenas verifique suas variáveis.

Miguel Suarez
fonte
0

Duplicatas em um repetidor não são permitidas. Use a expressão 'rastrear por' para especificar chaves exclusivas.

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

Exemplo

<!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
fonte
2
Por favor, declare toda a afiliação a todos os links que você postar
Draken
0

Se você chamar ng-repeat dentro de uma tag <ul>, poderá permitir duplicatas. Veja este link para referência. Veja Todo2.html

O desconhecido
fonte
-1

Minha JSONresposta foi assim:

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

Então, eu costumava ng-repeat = "item in variables.items" exibi-lo.

Jay
fonte
-1

Duplicatas em um repetidor não são permitidas. Use a expressão 'rastrear por' para especificar chaves exclusivas. Repetidor: sdetail em mydt, Chave duplicada: string:, Valor duplicado:

Eu enfrentei esse erro porque eu tinha escrito o nome do banco de dados errado na minha parte da API do PHP ......

Portanto, esse erro também pode ocorrer quando você está buscando os dados da base de dados, cujo nome está escrito incorretamente por você.

Vishal Solanki
fonte