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

前端 未结 9 1425
梦谈多话
梦谈多话 2020-12-05 00:47

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

相关标签:
9条回答
  • 2020-12-05 01:17

    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

    0 讨论(0)
  • 2020-12-05 01:17

    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...

    0 讨论(0)
  • 2020-12-05 01:22

    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>
    
    0 讨论(0)
提交回复
热议问题