Помилка кутового повторення ng "Дублікати у повторювачі не дозволені".


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-повтор, де використовується фільтр, вкладається в інший ng-повтор

Фільтр визначається так:

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

Відповіді:


955

Тут реально описано рішення: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

AngularJS не допускає дублікатів у директиві повторення ng. Це означає, що якщо ви намагаєтесь зробити наступне, ви отримаєте помилку.

// 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. Оскільки в цьому сценарії об’єкти не мають інших властивостей, це прекрасно працює. Причиною цієї помилки є те, що кутовий використовує словник для зберігання ідентифікатора елемента як ключа зі значенням як посилання DOM. З коду (рядок 15402 в angular.js) виглядає так, що вони кешують раніше знайдені елементи DOM на основі їх ключа в якості оптимізації продуктивності. Оскільки їм потрібні унікальні ключі, вони явно кидають цю помилку, коли знаходять повторювані ключі на лінії 15417
devshorts

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

21
Yikes, який безглуздо гадкий дизайн з боку Angular. Було б дуже, дуже просто пропустити цю проблему під час розробки та тестування, оскільки ваш масив ніколи не містив дублікатів, лише щоб ваш додаток вибухнув у виробництві, коли він вперше потрапляє на дупи. Раніше я будував програми Angular, не знаючи про обмеження "no dupes"; Зараз мені здається, що я замислююся і цікавлюсь, чи я несвідомо автор зламаного коду.
Марк Амері

наша програма вибухнула через цю причину, і я не є кутовим розробником. Чи $indexіснує змінна десь?
Чанг Чжао

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

45

Для тих, хто очікує, що JSON і все ще отримує таку ж помилку, переконайтесь, що ви аналізуєте свої дані:

$scope.customers = JSON.parse(data)

4
це не працює для мене, я очікую json після використання послуги $ http, але SyntaxError: Несподіваний маркер o на Object.parse (рідний)
Аврелій

1
@Fergus радий, що це працює для вас; однак переконайтесь, що шукаєте різницю між JSON.parse та JSON.stringify, якщо ви вже не знаєте.
корисноБе

2
Божевільний. Після місяців коректної роботи Angular різко вирішив, що JSON повернувся з $ http () більше не JSON. Явний розбір вирішив цю проблему для нас. Дякую за шалену пропозицію.
Ерік Л.

12

У мене виникла проблема в моєму проекті, коли я використовував ng-повторний трек за $ index, але продукти не відображалися, коли дані надходять із бази даних. Мій код наведений нижче:

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

У наведеному вище коді продукт - це окрема директива для відображення продукту. Але я дізнався, що $ index викликає проблему, коли ми передаємо дані із сфери застосування. Тож втрати даних та DOM неможливо оновити.

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

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

Але наведений вище код знову не працює та видаляє помилку нижче, коли більше одного продукту має той самий ідентифікатор:

angular.js: 11706 Помилка: [ngRepeat: dupes] Дублікати в ретрансляторі заборонено. Використовуйте вираз "слід за", щоб вказати унікальні клавіші. Повторювач

Тож нарешті я вирішив проблему, зробивши динамічний унікальний ключ ng-повтору, як нижче:

<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 викликає будь-яку проблему у випадку, то ми можемо використовувати будь-яку логіку із треком, за допомогою якого створюється ідентифікатор унікально.
Махіма Агравал

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. Не потрібно було додаткового "сліду за $ індексом".

На щастя, мені було передано це посилання на це обгрунтування:

.json стає важливим типом файлу в SP2010. SP2010 включає певні кінцеві точки веб-сервісу. Розташування цих файлів - це папка 14 вуликів \ isapi. Розширення цих файлів - .json. Ось чому вона призводить до такої помилки.

"дбає лише про те, що вміст файлу json є json, а не його розширення файлу"

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


0

На випадок, якщо це трапляється з кимось іншим, я це документую тут, я отримував цю помилку, оскільки я помилково встановив ng-модель таким же, як і ng-повторний масив:

 <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

Дублікати в повторювачі не дозволяються. Використовуйте вираз "слід за", щоб вказати унікальні клавіші.

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-повтор у тезі <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

Дублікати в повторювачі не дозволяються. Використовуйте вираз "слід за", щоб вказати унікальні клавіші. Повторювач: sdetail в mydt, повторюваний ключ: string:, значення, що повторюється:

Я зіткнувся з цією помилкою, тому що я написав неправильну назву бази даних у своїй частині програми PHP ......

Таким чином, ця помилка може також виникати, коли ви отримуєте дані з бази даних, чиє ім’я ви написали неправильно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.