Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS Ng-repeat and Duplicates

I have seen few questions in SO discussing no duplicates allowed in ng-repeat. My question is little different. In my case I am confused because I am not getting the error even if there are duplicate objects in array

Here is my HTML code

<table>
      <tr ng-repeat="item in items">
        <td> {{ item.email}}</td>           
      </tr>
</table>

And here is the code for populating the array

app.controller('MainCtrl', function($scope) {


$scope.items=[];

  $scope.items.push({
           "id":"1",
           "email":"[email protected]"});
  $scope.items.push({
           "id":"1",
           "email":"[email protected]"});

  $scope.items.push({
           "id":"2",
           "email":"[email protected]"});
  $scope.items.push({
           "id":"2",
           "email":"[email protected]"});


});

As per my understanding I should get the error and there are duplicate objects in array

However its getting rendered perfectly. Here is the plunker link

ng-repeat-demo

Obviously I am missing something basic. Can somebody point out my gap in understanding?

EDIT

Here is what in my application I was facing (only email ids are changed for obvious reason)

ExampleApp.filter("extractEmail", function (){

  return function(items){
    //console.log("test" + input[0].highlight.file[0]);
    var filtered = [];

    console.log(" items == " + items);


    angular.forEach(items, function(item){

      if (item){
        var obj = item.highlight.file[0].toString().match(/([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/);

      if (obj) {
        //console.log(obj[0]);
        filtered.push(obj[0]);
      }

      }


    }); 

    console.log(filtered);
    return filtered;
  }

});

my console.log prints [“[email protected]", “[email protected]", “[email protected]", “[email protected]"]

the error I get

Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: x in clusterState| extractEmail, Duplicate key: string:[email protected], Duplicate value: “[email protected]"

I updated the plunker with similar code. Not able to reproduce

Second Edit

The problem was with the version I was using: Angular JS 1.0.x supported duplicates not able to reproduce http://plnkr.co/edit/qrOez7aZ7X1jsOrmkfiP?p=preview

With the later version able to reproduce

http://plnkr.co/edit/q3oPCrW3RepxvWSZ1LB1?p=preview

like image 572
Abhijit Mazumder Avatar asked May 16 '15 16:05

Abhijit Mazumder


People also ask

How do you prevent duplicates in NG-repeat?

You can use unique filter while using ng-repeat . If you use track by $index then unique won't work.

What is Ng-repeat in AngularJS?

AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.

How do you pass an index in NG-repeat?

Each ng-repeat creates a child scope with the passed data, and also adds an additional $index variable in that scope. So what you need to do is reach up to the parent scope, and use that $index . Save this answer.

What is $Index in AngularJS?

Stay on the bleeding edge of your favorite technologies. $index is a way to show which iteration of a loop you're in. If we set up an ng-repeat to repeat over the letters in 'somewords', like so: <div ng-app="app"> <div ng-repeat="item in 'somewords'.split('')"> {{$index + 1}}. {{item}} </div> </div>


2 Answers

Objects in javascript are compared by reference, not by value.
It really doesn't matter if the contents of an object is exactly the same as another one, if the references doesn't points to same object, they are different.
E.g.:

// In this case "var a" and "var b" points to different objects.
var a = {};
var b = {};

a == b; // false

// Here, they points to the same one
var a = {};
var b = a;

a == b; // true

If you need every entry to be distinct you must check every entry yourself.
Angular ngRepeat have a syntax variation that uses track by to let you decide which entry is distinct (or duplicated).

<div ng-repeat="entry for entries track by entry.id">{{entry.email}}</div>
like image 107
NemoStein Avatar answered Oct 12 '22 23:10

NemoStein


The items are not considered equal because they point to different references.

If you were to track by ID, then you would get an error because the IDs are equal.

<tr ng-repeat="item in items track by item.id">
  <td> {{ item.email}}</td>           
</tr>

See this fiddle: http://jsfiddle.net/aj_r/7d4n9z0u/

like image 39
AJ Richardson Avatar answered Oct 12 '22 22:10

AJ Richardson