ng-sortable icon indicating copy to clipboard operation
ng-sortable copied to clipboard

Incorrect reordering when using track by $index

Open mritzco opened this issue 9 years ago • 10 comments

Elements get randomly reordered after a drag when using "track by $index"

I'm using "track by $index" because my list have dupes that are not allowed in an ng-repeat, you can check it out here: http://plnkr.co/edit/iVEdhGNFbWkwgwTI5oG7?p=preview

mritzco avatar Mar 13 '15 04:03 mritzco

+1. I ran into it also. but it's not reorder, or add one more item in model

al002 avatar Mar 23 '15 07:03 al002

It also has a weird behavior when using orderBy:'value'. Some help?

Thanks

mrchacon avatar May 08 '15 17:05 mrchacon

For the problem with "track by", you can define your own "track by" function :

$scope.UniqueTracking = function(index, id){
    return index + id
}

and use it like this :

ng-repeat="(itemNb, item) in items track by UniqueTracking(itemNb, item.id)"

pfouque avatar May 28 '15 08:05 pfouque

That works perfectly! Thanks @pfouque

I modified the plnkr with your solution, not sure if I should close the issue or if this can be somehow be built into ng-sortable. (@a5hik) Sample with fix: http://plnkr.co/edit/l93UJLmLHhjweLVPGORb?p=preview

mritzco avatar May 28 '15 09:05 mritzco

Great work @pfouque. Haven't come across that trick before. Had to modify the function to return a random unique id but you've saved me a few hours I feel! Thanks!

ghost avatar Jun 07 '15 06:06 ghost

I have the same problem , thank you @pfouque

niuxiufeng avatar Jun 10 '15 06:06 niuxiufeng

+1 for @pfouque's solution, hopefully the directive itself can be patched.

brianfeister avatar Oct 31 '15 22:10 brianfeister

You can add a dash or something to split the id and index, in case the id is also a number . If not you may still get an issue if you have sums that end up the same. ie (index 0 + id 4) is the same as (1 index + id 3)

iamakimmer avatar May 16 '16 17:05 iamakimmer

Addition to @pfouque 's answer, you don't really have to use a new function. You can just do the operation inline;

ng-repeat="item in items track by $index + item"

I'm guessing, This works because we are creating a new uniq id other than $index which is probably keep overlaping while the order is changing by ng-sortable.

btk avatar Aug 24 '16 14:08 btk

I've been struggling with this one for a while and just now discovered that there is a solution built into the module by @a5hik. For me, the problem is that I wanted to allow duplicate items and it would clean them up and remove them even when I was properly setting a unique ID instead of $index. Simply enabling allowDuplicates in conjunction with a unique hash instead of $index was ultimately the fix.

$scope.dragControlListeners = {
    allowDuplicates: true //optional param allows duplicates to be dropped.
};
<div as-sortable="dragControlListeners">

brianfeister avatar Feb 21 '17 20:02 brianfeister