myślę początkowe rozwiązanie jest rodzaj hacky ... ale tutaj jest robocza edycja wykorzystująca ją jako podstawę.
Problem polega na tym, że rozwiązanie zależy od pozycji dodawanych do powtórzenia ng. Jeśli spojrzysz na dyrektywę scrollItem, spowoduje to tylko, że dyrektywa keepScroll ponownie dopasuje scrollTop, jeśli linker zostanie wykonany. Dzieje się tak tylko wtedy, gdy elementy zostaną dodane, a nie usunięte.
Edycja zamiast tego słucha zdarzenia scope.$on('$destroy')
. Problem w tym momencie polega jednak na tym, że element nie ma już pozycji ClientHeight, ponieważ został usunięty z DOM. Rozwiązaniem jest zapisanie jego wysokości, gdy zostanie utworzone, a następnie powiedzenie keepScroll, jaka była wysokość usuniętego elementu.
Uwaga: Wydaje się, że spowodował to przewinięcie przewijania, jeśli przewijacz znajdował się na samym dole, więc musisz zajrzeć do tej sprawy jako wyjątek.
robocza JSBin: http://jsbin.com/geyapugezu/1/edit?html,css,js,output
Dla porównania:
HTML
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0-beta.7/angular.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app="Demo" ng-controller="DemoCtrl">
<div class="wrapper" keep-scroll>
<div class="item" scroll-item ng-repeat="item in items | orderBy: 'id'">
{{ item.name }}
</div>
</div>
<button ng-click="removeItem()">
Remove item
</button>
</body>
</html>
CSS
.wrapper {
width: 200px;
height: 300px;
border: 1px solid black;
overflow: auto;
}
.item {
background-color: #ccc;
height: 100px;
margin-bottom: 1px;
}
JS
angular.module("Demo", [])
.controller("DemoCtrl", function($scope) {
$scope.items = [];
for (var i = 0; i < 10; i++) {
$scope.items[i] = {
id: i,
name: 'item ' + i
};
}
$scope.removeItem = function() {
$scope.items = $scope.items.slice(1);
};
})
.directive("keepScroll", function(){
return {
controller : function($scope){
var element = 0;
this.setElement = function(el){
element = el;
};
this.itemRemoved = function(height){
element.scrollTop = (element.scrollTop - height - 1); //1px for margin
console.log("Item removed", element.scrollTop);
};
},
link : function(scope,el,attr, ctrl) {
ctrl.setElement(el[0]);
}
};
})
.directive("scrollItem", function(){
return {
require : "^keepScroll",
link : function(scope, el, att, scrCtrl){
var height = el[0].clientHeight;
scope.$on('$destroy', function() {
scrCtrl.itemRemoved(height);
});
}
};
});
EDIT
Albo to zrobić. Nie ma potrzeby używania scrollItem, zamiast tego oglądamy zmiany w elementach powtarzających ng i odpowiednio dostosowujemy scrollTop.
JSBin: http://jsbin.com/dibeqivubi/edit?html,css,js,output
JS
angular.module("Demo", [])
.controller("DemoCtrl", ['$scope', function($scope) {
$scope.items = [];
for (var i = 0; i < 10; i++) {
$scope.items[i] = {
id: i,
name: 'item ' + i
};
}
$scope.removeItem = function() {
$scope.items = $scope.items.slice(1);
};
}])
.directive("keepScroll", function() {
return {
link : function(scope,el,attr, ctrl) {
var scrollHeight;
scope.$watchCollection('items', function(n,o) {
// Instantiate scrollHeight when the list is
// done loading.
scrollHeight = scrollHeight || el[0].scrollHeight;
// Adjust scrollTop if scrollHeight has changed (items
// have been removed)
el[0].scrollTop = el[0].scrollTop - (scrollHeight - el[0].scrollHeight);
// Remember current scrollHeight for next change.
scrollHeight = el[0].scrollHeight;
});
}
};
});
HTML
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0-beta.7/angular.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app="Demo" ng-controller="DemoCtrl">
<div class="wrapper" keep-scroll>
<div class="item" ng-repeat="item in items | orderBy: 'id'">
{{ item.name }}
</div>
</div>
<button ng-click="removeItem()">
Remove item
</button>
</body>
</html>
To najlepsze rozwiązanie. Bardzo kompletny i zgodny z dobrą praktyką kątową. Jak już wspomniano, w przypadku obu rozwiązań przewijanie do dołu i kliknięcie przycisku usuwania powoduje przewijanie do wybranej pozycji. Jaka byłaby tego przyczyna? –