AngularJS:应用DOM更改后滚动到元素末尾

39

我有一个简单的项目列表,每当我添加更多的项目时,我希望能够滚动到显示项目的元素底部。我了解到没有办法钩入到$apply()函数的结尾,那么我的解决方案可能是什么?

这里有一个jsfiddle来说明我的问题。添加足够的项目后,ul元素不会滚动到底部...

6个回答

70

有一个非常棒的angularjs-scroll-glue可用,它可以做你想要的事情。

你所需要做的就是将scroll-glue指令应用到你的容器元素上,然后你就会得到你要找的东西。

这里也有一个演示可用。


3
这是一个不错的解决方案,但我不想使用太多外部库。你知道如何编写代码吗? - John Nguyen
3
@JohnNguyen说:“好的,这是开源的。” - Oliver Salzburg
2
值得依赖。这种观察DOM然后进行滚动的过程会生成不必要的代码。在这种情况下,这个库非常适合。 - Guilherme Oliveira

29

另一个有效的解决方案是使用 $timeout。使用0的超时值,Angular将等待DOM被渲染后再调用您传递给 $timeout 的函数。因此,在向列表中添加元素后,您可以使用它来等待新元素被添加到DOM中,然后滚动到底部。

@Mark Coleman解决方案一样,这不需要任何额外的外部库。

var myApp = angular.module('myApp', []);

function MyCtrl($scope, $timeout) {
  $scope.list = ["item 1", "item 2", "item 3", "item 4", "item 5"];
  $scope.add = function() {
    $scope.list.push("new item");
    $timeout(function() {
      var scroller = document.getElementById("autoscroll");
      scroller.scrollTop = scroller.scrollHeight;
    }, 0, false);
  }
}
ul {
  height: 150px;
  overflow: scroll;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="MyCtrl">
    <button ng-click="add()">Add</button>
    <ul id="autoscroll">
      <li ng-repeat="item in list">{{item}}</li>
    </ul>
  </div>
</div>


或者你可以直接在链接中观看你的收藏,然后滚动到元素。此外,你可以轻松访问链接中的元素... - Void
这个解决方案让控制器意识到DOM,并直接操作它。这不算是非Angular的吗?最好在指令中完成这部分工作,也许会更好一些? - tom

9
一个简单的工作示例(不需要插件或指令)...
.controller('Controller', function($scope, $anchorScroll, $location, $timeout) {

  $scope.func = function(data) {

    // some data appending here...

    $timeout(function() {
      $location.hash('end');
      $anchorScroll();
    })
  }

})

对我起作用的技巧是使用$timeout包装anchorScroll命令,这样作用域得到解析,并自动滚动到页面底部的元素。

感谢您提供的好而简单的解决方案。它有效并帮助了我。 - Kas Elvirov
简单,但有一个注意事项,它会使用哈希值修改URL。 - Seth Flowers

6
您可以创建一个简单的指令,绑定一个点击处理程序,每次将<ul>滚动到底部。
myApp.directive("scrollBottom", function(){
    return {
        link: function(scope, element, attr){
            var $id= $("#" + attr.scrollBottom);
            $(element).on("click", function(){
                $id.scrollTop($id[0].scrollHeight);
            });
        }
    }
});

example on jsfiddle


谢谢Mark,这对我很有帮助。可以使用$timeout服务稍微更新一下。我已经在jsfiddle上更新了http://jsfiddle.net/w5Vgw/99/. - Dilip
虽然这是一个不错的指令,但它并没有解决问题。它会立即滚动,而不等待新元素添加到DOM中。 - zendu

2

-1
你可以使用AngularJS的自定义指令来实现这一点。
例如:
<ul style="overflow: auto; max-height: 160px;" id="promptAnswerBlock">

<li ng-repeat="obj in objectKist track by $index" on-finish-render="ngRepeatFinished">                                              

  app.directive('onFinishRender', function($timeout) {
    return {
        restrict : 'A',
        link : function(scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function() {
                    $('#promptAnswerBlock').scrollTop($('#promptAnswerBlock')[0].scrollHeight + 150);
                });
            }
          }
        }
    }); 

</li>

ng-repeat="attributevalue in attribute.attributeValueList track by $index" on-finish-render="ngRepeatFinished" - sohan kumawat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接