2015-11-15 28 views
7

移除項目時,如何留住在AngularJS NG重複的滾動位置我試圖從溶液中工作,這從頂部

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

達到保留滾動位置去除頂部時ng-repeat中的項目,但無法弄清楚這樣做的代碼。另外,請注意,列表應該按照與items數組相同的順序進行打印,而不是像例子那樣反向打印。

該解決方案的代碼:

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.addNewItem = function() { 
    $scope.items = $scope.items.concat({ 
     id: $scope.items.length, 
     name: "item " + $scope.items.length 
    }); 
    }; 
}) 

.directive("keepScroll", function(){ 

    return { 

    controller : function($scope){ 
     var element = 0; 

     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 
     }; 

    }, 

    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]); 
    } 
    } 
}) 

我想這樣做是由 'ID' 改變

element.scrollTop = (element.scrollTop + item.clientHeight+1) 

element.scrollTop = (element.scrollTop - item.clientHeight+1) 

和打印爲了不 '-id'

回答

5

我認爲最初的解決方案是一種哈克內事件中......但這是一個使用它作爲基礎的工作編輯。

問題是解決方案取決於添加到ng-repeat的項目。如果您查看scrollItem指令,則只會導致keepScroll指令在鏈接器得到執行時重新調整scrollTop。這隻發生在項目被添加,而不是被刪除。

編輯代替監聽scope.$on('$destroy')事件。然而,問題在於,該元素不再具有clientHeight,因爲它已從DOM中刪除。所以解決方法是在創建時保存它的高度,然後告訴keepScroll刪除元素的高度是多少。

注意:如果滾動條一直到底部,這似乎會導致滾動跳轉,所以您需要將該情況視爲例外情況。

工作JSBin:http://jsbin.com/geyapugezu/1/edit?html,css,js,output

參考:

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); 
     }); 
    } 
    }; 
}); 

編輯

或者說,做到這一點。不需要scrollItem,而是觀察對ng-repeat項目的更改並相應地重新調整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> 
+0

這是最好的解決方案。非常完整,遵循良好的角度做法。正如你所提到的,這兩種解決方案都是如果它滾動到底部並且點擊刪除項目按鈕,滾動會跳到某個任意位置。那會是什麼原因? –

0

我希望$anchorScroll可以幫助你。按照link

+0

這並沒有真正做什麼,我想它。並非所有項目都具有相同的高度,我不一定要滾動到該項目的頂部。 –

+1

但是,謝謝@ @okeshjain2008 –

0

我不確定我是否理解正確,但是您可以實現想要收聽要刪除的項目數組和項目的內容。

希望這將有助於

http://plnkr.co/edit/buGcRlVGClj6toCVXFKu?p=info

這裏就是我所做的:

新增的項目

for (var i = 0; i < 20; i++) { 
    $scope.items[i] = { 
     id: i, 
     name: 'item ' + i, 
     height: (Math.random()*100)+30 
    }; 
} 

style: height財產的HTML文件中height屬性

<div class="wrapper" keep-scroll> 
    <div class="item" scroll-item ng-repeat="item in items" style="height:{{item.height}}px"> 
     {{ item.name }} 
    </div> 
</div> 

deleteItem方法DemoCtrl

$scope.deleteItem = function() { 
    var itemToDelete = $scope.items[0]; 
    $scope.items.splice(0,1); 
    $scope.$broadcast("scrollFix",itemToDelete); 
}; 

比我聽scrollFixkeepScroll指令

$scope.$on('scrollFix',function(event,data){ 
    element.scrollTop = element.scrollTop - data.height; 
}); 
+0

爲什麼添加項目所需的高度屬性雖然不需要像以前鏈接的解決方案一樣去除它? –

+0

同時在根作用域上廣播一個事件並不是很好的做法。我想在原始解決方案中使用指令,並按照操作DOM元素的最佳做法。 –

+0

是的,你是對的穆罕默德。沒有必要爲項目定義高度。 Foglerek的解決方案更方便 – huseyinozcan