Угловая ошибка 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.

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

Если вы вызываете ng-repeat в теге <ul>, вы можете разрешить дублирование. Смотрите эту ссылку для справки. Смотрите Todo2.html

Неизвестный
источник
-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 ......

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

Вишал Соланки
источник