DEMO
List of objects is rendered using ng-repeat
. Suppose that this list is very long and user is scrolling to the bottom to see some objects.
While user is observing an object, a new item is added to the top of the list. This causes the observed object to change its position, i.e. the user suddenly sees something else at the same place of the observed object.
How would you go about keeping the observed object at the same place when new items are added?
PLAYGROUND HERE
The preserve scroll position setting lets you keep the same scroll location when you transition between screens. This applies to vertical scroll depth, as well as horizontal location. Figma automatically preserves your scroll position for Smart Animate.
But ng-repeat is not the right thing to use when you have large datasets as it involves heavy DOM manipulations. And you should consider using ng-repeat with pagination. You can consider using transclusion inside a custom directive, to achieve the behavior you are looking for without using ng-repeat.
To avoid this problem, you can use "track by" with ng-repeat. In track by you have to use angular expression that will be used to uniquely identify the each items in collection or model. "track by" tells the angular js that how angular js will track the association between DOM and the model (i.e. collection).
Note: The $index variable is used to get the Index of the Row created by ng-repeat directive. Each row of the HTML Table consists of a Button which has been assigned ng-click directive. The $index variable is passed as parameter to the GetRowIndex function.
It maybe solved quite elegantly, by using scrollTop
property of div
. I used two directives - one handles scroll position of the wrapper element, the other register new elements. Give me a shout if anything unclear.
DEMO
JS:
.directive("keepScroll", function(){ return { controller : function($scope){ var element = null; this.setElement = function(el){ element = el; } this.addItem = function(item){ console.log("Adding item", item, item.clientHeight); element.scrollTop = (element.scrollTop+item.clientHeight+1); //1px for margin from your css (surely it would be possible // to make it more generic, rather then hard-coding the value) }; }, link : function(scope,el,attr, ctrl) { ctrl.setElement(el[0]); } }; }) .directive("scrollItem", function(){ return{ require : "^keepScroll", link : function(scope, el, att, scrCtrl){ scrCtrl.addItem(el[0]); } } })
HTML:
<div class="wrapper" keep-scroll> <div class="item" scroll-item ng-repeat="item in items | orderBy: '-id'"> {{ item.name }} </div> </div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With