从顶部删除项目时如何在AngularJS中保留ng-repeat的滚动位置 [英] How to retain the scroll position of ng-repeat in AngularJS when removing an item from the top

查看:60
本文介绍了从顶部删除项目时如何在AngularJS中保留ng-repeat的滚动位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从解决方案着手解决这个问题

I tried to work from the solution to this

如何保留ng-repeat的滚动位置在AngularJS中?

在移除ng-repeat中的顶部项时实现保留滚动位置,但无法弄清楚这样做的代码.

to achieve retaining the scroll position when removing the top item in an ng-repeat but couldn't figure out the code to do so.

此外,请注意,列表的打印顺序应与items数组相同,而不是示例中的相反顺序.

Also, side note, the list should print in the same order as the items array, not in the reverse as the example does.

解决方案的代码:

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

我尝试做的是改变

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

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

并按'id'而不是'-id'的顺序打印

and printing in order by 'id' not '-id'

推荐答案

我认为最初的解决方案有点怪异...但是这里是一个以它为基础的有效编辑.

I think the initial solution is kind of hacky... but here's a working edit using it as the basis.

问题在于解决方案取决于添加到ng-repeat中的项目.如果您查看scrollItem指令,则只有在执行链接程序后,它才会使keepScroll指令重新调整scrollTop.这只会在添加但未删除项目时发生.

The problem is that the solution depends on items being added to the ng-repeat. If you look at the scrollItem directive, it only causes the keepScroll directive to readjust scrollTop if the linker gets executed. This only happens when items get added, not removed.

相反,编辑将侦听scope.$on('$destroy')事件.但是,此时的问题是,该元素不再具有clientHeight,因为它已从DOM中删除.因此解决方案是在创建时保存其高度,然后告诉keepScroll所删除元素的高度是什么.

The edit instead listens to the scope.$on('$destroy') event. The issue at that point is however, that the element no longer has a clientHeight because it has been removed from the DOM. So the solution is to save its height when it gets created, and then instead tell keepScroll what the height of the removed element was.

注意:如果滚动条一直滑到底部,这似乎会导致滚动跳动,因此您需要将这种情况视为例外.

工作中的JSBin: http://jsbin.com/geyapugezu/1 /edit?html,css,js,输出

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

EDIT

Or, do this. No need for scrollItem, instead we watch changes to the ng-repeat items and readjust the scrollTop accordingly.

JSBin: http://jsbin.com/dibeqivubi/edit?html, css,js,输出

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>

这篇关于从顶部删除项目时如何在AngularJS中保留ng-repeat的滚动位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆