Açısal ng-tekrarlama Hatası “Bir tekrarlayıcıdaki kopyalara izin verilmez.”


472

Ben böyle bir özel filtre tanımlıyorum:

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

Filtrenin kullanıldığı ng tekrarını başka bir ng tekrarına yerleştirdiğinizi görebilirsiniz

Filtre şu şekilde tanımlanır:

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

Ben alıyorum:

Hata: Tekrarlayıcıdaki kopyalara izin verilmez. Tekrarlayıcı: item.comments içinde yorum | aralık: 1: 2 ngRepeatAction @ https://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/an

Yanıtlar:


955

Çözüm aslında burada açıklanmıştır: http://www.anujgakhar.com/2013/06/15/duplicates-in-a-repeater-are-not-allowed-in-angularjs/

AngularJS, tekrarlama yönergesinde yinelemelere izin vermez. Bu, aşağıdakileri yapmaya çalışıyorsanız bir hata alacağınız anlamına gelir.

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

Bununla birlikte, aşağıdaki gibi benzersizliği belirlemek için bir endeksi tanımlamak için yukarıdaki kodu biraz değiştirmek, tekrar çalışmasını sağlayacaktır.

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

Resmi dokümanlar burada: https://docs.angularjs.org/error/ngRepeat/dupes


48
Sadece $ endeksi değil, benzersizliği tanımlamak için herhangi bir özel izleme özelliğini uygulayabileceğinizi belirtmek istedim. Bu senaryoda nesnelerin başka özellikleri olmadığından, bu iyi çalışır. Bu hatanın nedeni, açısalın, bir öğenin kimliğini DOM referansı değerine sahip anahtar olarak saklamak için bir sözlük kullanmasıdır. Koddan (angular.js'deki satır 15402), performans optimizasyonu olarak anahtarlarına dayanarak daha önce bulunan DOM öğelerini önbelleğe alıyor gibi görünüyor. Benzersiz anahtarlara ihtiyaç duydukları için 15417 satırında yinelenen anahtarlar bulduklarında açıkça bu hatayı atarlar
devshorts

16
<div ng-repeat="row in [1,1,1,2,2] |filter: 2 track by $index" >"arama filtresinin" $ endeksiyle takip et "tarihinden önce olması gerekiyor
Zhe Hu

21
Yikes, Angular kısmında anlamsızca kötü tasarım. Geliştirme ve test sırasında bu sorunu kaçırmak çok ama çok kolay olurdu, çünkü diziniz hiçbir zaman kopya içermiyordu, sadece uygulamanızın ilk kez çiftlere maruz kaldığında üretimde patlaması için. Daha önce "dupes" kısıtlaması bilmeden Açısal uygulamalar inşa ettik; Şimdi kendimi geri düşünüyor ve bilmeden kırık kod yazıp yazmadığımı merak ediyorum.
Mark Amery

bizim app bu nedenle patladı ve ben açısal geliştirici değilim, $indexdeğişken bir yerde var mı ?
Chang Zhao

dizi öğelerinizi daha sonra güncelleştirirseniz, eski verileri göstermek yerine DOM etiketlerini yeniden derlemeyecek bir uyarı olduğunu unutmayın. track by ($index + ':' + row)Böylece <ng-repeat>, verileri güncellediğinde ve yeni bir öğe eklendiğinde, çiftleri açmadan güncellemek için kullanabilirsiniz
Hashbrown

45

JSON'u bekleyip hala aynı hatayı alan kullanıcılar için verilerinizi ayrıştırdığınızdan emin olun:

$scope.customers = JSON.parse(data)

4
Bu benim için çalışmıyor, $ http hizmeti kullandıktan sonra json bekliyoruz, ancak SyntaxError: Object.parse (yerli) de beklenmedik token o
aurelius

1
@Fergus bunun sizin için çalışmasından memnun; ancak, bilmiyorsanız JSON.parse ve JSON.stringify arasındaki farkı aradığınızdan emin olun.
usefulBee

2
Çılgın. Aylarca düzgün çalıştıktan sonra, Angular aniden $ http () 'den dönen JSON'un artık JSON olmadığına karar verdi. Açıkça ayrıştırmak bu sorunu bizim için çözdü. Çılgın öneri için teşekkürler.
Eric L.

12

Projemde $ endeksi ile ng-yineleme parçasını kullandığım bir sorun yaşıyordum, ancak veriler veritabanından geldiğinde ürünler yansıtılmıyordu. Kodum aşağıdaki gibidir:

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

Yukarıdaki kodda, ürün ürünü görüntülemek için ayrı bir direktif.Ancak $ endeksinin kapsamdan veri aktardığımızda soruna neden olduğunu öğrendim. Böylece veri kayıpları ve DOM güncellenemez.

Aşağıdaki gibi ng-repeat içinde bir anahtar olarak product.id kullanarak çözümü buldum:

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

Ancak yukarıdaki kod yine başarısız olur ve birden fazla ürün aynı kimliğe sahip olduğunda aşağıdaki hatayı atar:

angular.js: 11706 Hata: [ngRepeat: dupes] Bir tekrarlayıcıdaki kopyalara izin verilmiyor. Benzersiz anahtarlar belirtmek için 'takip etme' ifadesini kullanın. tekrarlayıcı

Sonunda aşağıdaki gibi ng-tekrar dinamik benzersiz anahtar yaparak sorunu çözdü:

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

Bu, sorunumu çözdü ve umarım bu gelecekte size yardımcı olacaktır.


1
Elbette track by $indexbundan daha iyi olur track by (product.id + $index)mu? Birincisi, track by $indexdaha basit ve bir diğeri için, muhtemelen değerlerinin (product.id + $index)benzersiz olacağına dair herhangi bir garantiniz yoktur . Örneğin, diziniz 5'li bir ürünle başlıyor idve bundan sonra id4'lü bir ürün varsa , değerlerinin (product.id + $index)her ikisi de 5 olacaktır (ilk ürün için 5 + 0, ikinci için 4 + 1) ve hala olsun bir tekrarlayıcı içinde Yinelemelere izin verilmiyor hatası.
Mark Amery

1
Ben $ endeksi daha basit olduğunu kabul ediyorum ama yukarıdaki çözüm benim için $ endeksi ile karşı karşıya tüm sorunları çözmek için çalıştı. Ve benim durumumda product.id alfasayısaldır, bu nedenle (product.id + $ index) hiçbir durumda çoğaltılamaz. Bu nedenle, bu çözümün arkasındaki fikir, $ index bir durumda herhangi bir soruna neden oluyorsa, benzersiz bir şekilde oluşturulan kimlikle herhangi bir mantığı kullanabiliriz.
Mahima Agrawal

5

"Aralık" filtrenizin ne yapmasını istersiniz?

İşte yapmaya çalıştığınızı düşündüğüm bir örnek : 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

Şans eseri SharePoint 2010 ile çalışırken bu hata oluşursa: .json dosya uzantılarınızı yeniden adlandırın ve restService yolunuzu güncellediğinizden emin olun. Ek "$ endeksine göre takip et" gerekmez.

Neyse ki bu bağlantıyı bu gerekçeye yönlendirdim:

.json, SP2010'da önemli bir dosya türü haline gelir. SP2010, bazı web hizmet bitiş noktalarını içerir. Bu dosyaların konumu 14hive \ isapi klasörüdür. Bu dosyaların uzantısı .json'dur. Böyle bir hata vermesinin nedeni budur.

"sadece bir json dosyasının içeriğinin dosya uzantısı değil json olduğunu umursar"

Dosya uzantıları değiştirildikten sonra ayarlanmalıdır.


0

Sadece bu başka birine olur, ben burada belgelemek, yanlışlıkla ng-modeli ng-tekrar dizisi ile aynı ayarlamak çünkü bu hatayı alıyorum:

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

Onun yerine:

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

Diziyi kontrol ettim ve kopyaları yoktu, sadece değişkenlerinizi iki kez kontrol edin.


0

Tekrarlayıcıdaki kopyalara izin verilmez. Benzersiz anahtarlar belirtmek için 'takip etme' ifadesini kullanın.

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

Misal

<!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
Lütfen gönderdiğiniz tüm bağlantılara ait tüm bağlılıkları beyan edin
Draken

0

<Ul> etiketi içinde bir ng tekrarını çağırırsanız, kopyalara izin verebilirsiniz. Referans için bu bağlantıya bakın. Bkz. Todo2.html


-1

Cevabım şöyle 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"
    }]
}

Yani, ben ng-repeat = "item in variables.items" onu gösteriyordum.


-1

Tekrarlayıcıdaki kopyalara izin verilmez. Benzersiz anahtarlar belirtmek için 'takip etme' ifadesini kullanın. Tekrarlayıcı: mydt cinsinden sdetail, Yinelenen anahtar: string:, Yinelenen değer:

Ben php api bölümünde yanlış veritabanı adı yazmıştı çünkü bu hatayla karşı karşıya ......

Bu nedenle, adı sizin tarafınızdan yanlış yazılmış olan veritabanı tabanından veri alırken de bu hata oluşabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.