I'm working on a project in angularjs that has a list of objects which update in real time and will be reordered with each update. I want to animate these objects moving smoothly from their starting to their end positions, so for example when the list reorder is:
A C
B -> A
C B
A and B will each move down one spot, and C will move up two spots, twice as quickly. This is easily done when you are manipulating the DOM manually - if you are moving the list element by changing it's style.top, you just put
transition-duration: 0.5s, 0.5s;
transition-property: top;
into the CSS for the element and it happens automatically. However, this trick won't work if you are using ngRepeat to display your list, because (as far as I can tell) angular actually recreates the DOM elements making up the list to do an update, rather than moving the DOM elements around.
Unfortunately, I've found it really difficult to reproduce this functionality with angular animations. The problem that I'm running into is that angular move animations seem to be unaware of each element's starting position. With the ngAnimate directive you can have angular automatically set a css class on your element when it moves, to simulate it fading in or out for example. But you have no information on where the element used to be, so you can't move it smoothly from it's old position - it just gets teleported to the new spot, and you have to make it dance around there. As far as I can tell, this is also true for javascript animations - angular teleports it into place and then passes it to your function, without any history information.
Is there a way within angular to have a smooth reordering animation as described above, without ditching the framework and handling the DOM manipulation yourself?
I think I've accomplished what you're looking for here: http://codepen.io/daleyjem/pen/xbZYpY
By using track by
, I'm able to keep the DOM elements from being recreated, and can then manipulate their position.
<div ng-repeat="item in items | orderBy:sorter track by item.id" class="item" jd-script>
{{ item.id }}: {{ item.last_name }}, {{ item.first_name }}
</div>