Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retain scroll position of ng-repeat in AngularJS?

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

like image 920
Misha Moroshko Avatar asked May 19 '14 11:05

Misha Moroshko


People also ask

How do you keep the scroll position?

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.

What can I use instead of NG-repeat?

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.

How do I use track in 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).

How do I get the index of an element in NG-repeat?

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.


1 Answers

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> 
like image 56
artur grzesiak Avatar answered Oct 11 '22 00:10

artur grzesiak