marceljuenemann / angular-drag-and-drop-lists

Angular directives for sorting nested lists using the HTML5 Drag & Drop API
MIT License
2.16k stars 713 forks source link

Anuglar error : Duplicates in a repeater are not allowed #478

Open nlips opened 6 years ago

nlips commented 6 years ago

My list of item is a simple list of string. When I move an item angular throw the error "Duplicates in a repeater are not allowed" because the item appears 2 times in the list. The dnd-moved callback is called after the angular digest loop. Why? How to get around this problem? Sample here : https://jsfiddle.net/nlips/bhp9Lrxa/

iiminov commented 6 years ago

Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: item in list, Duplicate key: string:AAA, Duplicate value: AAA

Is a classic ng-repeater error. I suspect this is a combination of two issues:

  1. You're using a simple string array
  2. Before dnd-moved actually executes its logic dnd-draggable inserts the item which is getting moved

As a result, you end up inserting another string item into the array before the old item at specific $index gets removed. And that's where ng-repeater comes in. It detects that it has two identical values and throws you an error above.

If you were to define your $scope.list as an array of objects is suspect the issue would go away.

$scope.list = [ { Name: "AAA" }, { Name: "BBB" }, { Name: "CCC" } ]; // array structure
{{item.Name}} // additional change to data binding required

Reason behind change is that angular would define $$hashKey property with unique ObjectId ("object:42") as its value.

I am just speculating here but I suspect when you perform the drag-and-drop action, in the background angular.copy(item) operation gets used to copy the item that needs to be inserted into the array before the old item is removed.

Going back to your example, if you pass a string into angular.copy you will get exactly the same string back. But if you were to pass an object you will get the same object but with a different $$hashKey value.

So, when the ng-repeater looks at it's new list of objects after the insertion (just before the old item is removed) it doesn't see any duplicates becuase it is looking at the value of $$hashKey instead of comparing object properties for equality (which would be time consuming operation).

And I will have to say this one more time. I am just speculating here. I did not look at the angular-drag-and-drop-lists implementation. But I have had ng-repeater complain to me about duplicate entries before.

If you make the changes proposed above your issue will go away, ng-repeater will stop complaining about duplicate entries in your sample fiddle.

uofmmike commented 5 years ago

I realize this is an old thread, but i'd recommend this approach: https://github.com/marceljuenemann/angular-drag-and-drop-lists/issues/414#issuecomment-306038315