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.
W
You need to add a scrollspy directive to your container that updates its position on every user scroll, and gets notified on every repeat render so it can reposition it self to its saved state. your html might look like this
<div scrollspy id="myscrollspy">
<ul>
<li ng-repeat="" notifyscroll></li>
</ul>
</div>
the scroll spy would have the required css overflow settings and scroll-x or scroll-y to keep track of the current scroll and avoid polluting the scope it should also watch for an event comming from the ng-repeat that tells him a change occured and should set the scrool.
ng-repeat could notify by attaching a new directive notify scroll that launches an event. not sure if curretn version of angular supports postrender event.
the way to position the scroll will depend on whether you are using a 3rd party library $.scrollTop(pos) or no. this will do it or should. hope it helps
There are, I believe, only a few possible solutions
1) Don't add the item (as per the other answer)
2) Add the item at bottom, so the list doesn't move.
3) Add the item at top and scroll the screen automatically so that the new item's height is accounted for, and everything is kept seemingly as before. The list will move down, but the viewable screen itself will also move - so relatively nothing will be seen to move. Well other elements that are not part of list will, but that might actually look quite nice...
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>