Угловая ошибка ng-repeat «Дубликаты в повторителе не допускаются».


472

Я определяю пользовательский фильтр следующим образом:

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

Как вы можете видеть, ng-repeat, где используется фильтр, вложен в другой ng-repeat

Фильтр определяется так:

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

Я получаю:

Ошибка: дубликаты в повторителе не допускаются. Повторитель: комментарий в item.comments | диапазон: 1: 2 ngRepeatAction @ https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

Ответы:


954

Решение на самом деле описано здесь: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

AngularJS не допускает дублирования в директиве ng-repeat. Это означает, что если вы пытаетесь сделать следующее, вы получите ошибку.

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

Однако, слегка изменив приведенный выше код, чтобы определить индекс для определения уникальности, как показано ниже, он снова заработает.

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

Официальные документы доступны здесь: https://docs.angularjs.org/error/ngRepeat/dupes.


48
Я хотел упомянуть, что вы можете применять любое пользовательское свойство отслеживания для определения уникальности, а не только $ index. Так как в этом сценарии объекты не имеют никаких других свойств, это прекрасно работает. Причина, по которой эта ошибка возникает, заключается в том, что angular использует словарь для хранения идентификатора элемента в качестве ключа со значением в качестве ссылки DOM. Из кода (строка 15402 в angular.js) похоже, что они кэшируют ранее найденные элементы DOM на основе их ключа в качестве оптимизации производительности. Поскольку им нужны уникальные ключи, они явно выдают эту ошибку, когда находят повторяющиеся ключи в строке 15417
devshorts

16
<div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" >«фильтр поиска» должен быть до «отслеживания по $ index»
Чжэ Ху,

21
Yikes, какой бессмысленно противный дизайн со стороны Angular. Было бы очень и очень легко пропустить эту проблему во время разработки и тестирования, потому что ваш массив никогда не содержал дубликатов, только чтобы ваше приложение взорвалось в рабочем состоянии, когда оно впервые подверглось дублированию. Раньше я создавал приложения для Angular, не зная об ограничении «нет дубликатов»; Теперь я снова вспоминаю и задаюсь вопросом, не бессознательно ли я написал неработающий код.
Марк Эмери

наше приложение взорвалось по этой причине, и я не угловой разработчик, $indexсуществует ли переменная где-то?
Чанг Чжао

Заметьте, что если вы обновите элементы массива позже, то это не приведет к повторной компиляции тегов DOM, вместо этого будут показаны устаревшие данные. Вы можете использовать track by ($index + ':' + row)его так, чтобы он обновлял отдельные <ng-repeat>s всякий раз, когда обновляются его данные, а также когда добавляется новый элемент, без отключения
дубликатов

45

Для тех, кто ожидает JSON и все еще получает ту же ошибку, убедитесь, что вы анализируете свои данные:

$scope.customers = JSON.parse(data)

4
это не работает для меня, я ожидаю, что json, после использования службы $ http, но SyntaxError: Неожиданный токен o в Object.parse (нативный)
aurelius

1
@Fergus рад, что это работает для вас; однако, убедитесь, что вы ищете разницу между JSON.parse и JSON.stringify, если вы уже не знаете.
полезноBee

2
Сумасшедший. После нескольких месяцев правильной работы Angular внезапно решил, что JSON, возвращенный из $ http (), больше не является JSON. Явный разбор решил эту проблему для нас. Спасибо за сумасшедшее предложение.
Эрик Л.

12

У меня возникла проблема в моем проекте, когда я использовал трек ng-repeat по $ index, но продукты не отражали данные, поступающие из базы данных. Мой код, как показано ниже:

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

В приведенном выше коде product - это отдельная директива для отображения продукта. Но я узнал, что $ index вызывает проблему, когда мы передаем данные из области. Таким образом, потери данных и DOM не могут быть обновлены.

Я нашел решение, используя product.id в качестве ключа в ng-repeat, как показано ниже:

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

Но приведенный выше код снова дает сбой и выдает приведенную ниже ошибку, когда более одного продукта поставляется с одинаковым идентификатором:

angular.js: 11706 Ошибка: [ngRepeat: dupes] Дубликаты в повторителе не допускаются. Используйте выражение «track by» для указания уникальных ключей. повторитель

Наконец, я решил проблему, создав динамический уникальный ключ ng-repeat, как показано ниже:

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

Это решило мою проблему и надеюсь, что это поможет вам в будущем.


1
Конечно track by $index, будет лучше, чем track by (product.id + $index)? С одной стороны, track by $indexэто проще, а с другой, у вас, вероятно, нет никакой гарантии, что значения (product.id + $index)будут уникальными. Например, если ваш массив начинается с продукта с id5, а после этого есть продукт с id4, их значения (product.id + $index)будут равны 5 (5 + 0 для первого продукта, 4 + 1 для второго), и вы будете все равно получить дубликаты в повторителе не допускается ошибка.
Марк Амери

1
Я согласен с тем, что $ index проще, но вышеупомянутое решение работает для меня, чтобы решить все проблемы, с которыми я столкнулся с $ index. И в моем случае product.id является буквенно-цифровым, поэтому (product.id + $ index) ни в коем случае нельзя дублировать. Таким образом, идея этого решения состояла в том, что если $ index вызывает какие-либо проблемы в кейсе, то мы можем использовать любую логику с треком, по которой уникальным образом создается id.
Махима Агравал

5

Что вы собираетесь делать с вашим «диапазонным» фильтром?

Вот рабочий пример того, что я думаю, вы пытаетесь сделать: 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

Если случайно эта ошибка возникает при работе с SharePoint 2010: переименуйте ваши расширения файлов .json и обязательно обновите ваш путь restService. Никаких дополнительных «track by $ index» не требуется.

К счастью, я был перенаправлен по следующей ссылке :

.json становится важным типом файлов в SP2010. SP2010 включает определенные конечные точки веб-сервиса. Расположение этих файлов - папка 14hive \ isapi. Расширение этих файлов .json. Вот почему это дает такую ​​ошибку.

«заботится только о том, что содержимое файла json - это json, а не его расширение»

После изменения расширений файлов все должно быть установлено.


0

На случай, если это случится с кем-то другим, я документирую это здесь, я получаю эту ошибку, потому что я по ошибке установил ng-модель так же, как массив 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>

Вместо:

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

Я проверил массив и не имел дубликатов, просто дважды проверьте ваши переменные.


0

Дубликаты в повторителе не допускаются. Используйте выражение «track by» для указания уникальных ключей.

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

пример

<!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
Пожалуйста, объявите всю принадлежность к любым ссылкам, которые вы
публикуете


-1

Мой JSONответ был таким:

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

Итак, я использовал его ng-repeat = "item in variables.items" для отображения.


-1

Дубликаты в повторителе не допускаются. Используйте выражение «track by» для указания уникальных ключей. Повторитель: sdetail в mydt, Дубликат ключа: строка:, Дубликат значения:

Я столкнулся с этой ошибкой, потому что я написал неправильное имя базы данных в моей части php api ......

Так что эта ошибка также может возникать, когда вы выбираете данные из базы данных, чье имя написано неверно вами.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.