2013-06-25 3 views
34

У меня есть простой список элементов. Я хочу иметь возможность прокручивать нижнюю часть элемента, отображающего элементы, когда я добавляю больше элементов. Я понял, что нет возможности подключиться к концу функции $apply(), так что может быть моим решением?AngularJS: Прокрутите до конца элемента после применения изменений DOM

Это jsfiddle, чтобы проиллюстрировать мою проблему. после добавления достаточного количества элементов ul элемент не прокручивается до нижней ...

ответ

69

Там в очень удивительным angularjs-scroll-glue доступны, что делает именно то, что вы хотите.

Все, что вам нужно сделать, это применить директиву scroll-glue к вашему элементу контейнера, и вы получите именно то, что ищете.

Имеется также demo.

+3

Это хорошее решение, но я не хочу использовать многие внешние библиотеки. вы знаете, как его кодировать? –

+3

@JohnNguyen: Ну, это [с открытым исходным кодом] (https://github.com/Luegg/angularjs-scroll-glue/blob/master/src/scrollglue.js). –

+2

стоит зависимости .. этот вид процесса просмотра DOM, а затем продолжить с помощью прокрутки создает ненужный код .. в этом случае эта библиотека идеально подходит. –

5

Вы можете создать простую директиву, которая связывает обработчик кликов, который каждый раз прокручивает <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

+0

Спасибо Марку это помогло мне. Это может быть немного лучше обновлено с помощью службы $ timeout. Я обновил jsfiddle http://jsfiddle.net/w5Vgw/99/. – Dilip

+0

Хотя это хорошая небольшая директива, она не решает проблему. Он прокручивается немедленно, не дожидаясь добавления нового элемента в DOM. – zendu

23

Другим верным решением для этого является использование $timeout. Используя значение тайм-аута 0, угловое будет ждать, пока DOM будет отображаться до вызова функции, которую вы передаете, до $timeout. Итак, после добавления элемента в список вы можете использовать это, чтобы дождаться добавления нового элемента в DOM перед прокруткой вниз.

Как @Mark Colemansolution, для этого не требуются дополнительные внешние библиотеки.

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>

+0

Или вы можете просто посмотреть свою коллекцию в ссылке, а затем прокрутить элемент. Также у вас есть легкий доступ к элементам в ссылке ... – Void

+0

Это решение позволяет контроллеру знать о DOM и непосредственно манипулировать им. Разве это не считалось бы не угловатым? Лучше сделать эту роль в директиве, возможно? – tom

5

Простой рабочий пример (нет необходимости плагинов или директив) ...

.controller('Controller', function($scope, $anchorScroll, $location, $timeout) { 

    $scope.func = function(data) { 

    // some data appending here... 

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

}) 

Трюк, который сделал это для меня было оборачивать anchorScroll команду с $timeout, таким образом область была решена и автоматически переместилась на элемент в конце страницы.

+0

Благодарим за хорошее и простое решение. Это работает и помогает мне) –

+0

Простой, но с оговоркой, что он изменяет URL с хэш-значением. –

-1

Вы можете добиться этого, используя пользовательский каталог углов.

пример:

<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> 
+0

ng-repeat = "attributevalue в атрибуте.attributeValueList track по $ index" on-finish-render = "ngRepeatFinished" –

+0

Отформатируйте свой код – adao7000

Смежные вопросы