【问题标题】:slice function in JavaScript not working for paginationJavaScript中的切片函数不适用于分页
【发布时间】:2016-02-29 12:51:34
【问题描述】:

我正在使用 Angularjs 做一个 Todo 应用程序。我尝试使用分页,每页只显示 5 个待办事项。我可以添加分页,但切片功能不适用于待办事项列表。

它表示未定义的切片函数。我得到了其未定义行为的原因。这是因为 todo 列表不在范围内,我需要以某种方式将 todo 列表取出,以便它可以用于下一个函数。但如果成功率为零,我可以让它成为可能。

这是我的控制器代码:

todoApp.controller('mainController', ['$scope', '$filter', 'Todos', function($scope, $filter, Todos) {
    $scope.formData = {};
    $scope.loading = true;
    $scope.count = 0;

    $scope.filteredTodos = [];   
    $scope.currentPage = 1;
    $scope.numPerPage = 5;
    $scope.maxSize = 5;

    // GET =====================================================================
    // when landing on the page, get all todos and show them
    // use the service to get all the todos
    //$scope.todos = [];
    Todos.get()
        .success(function(data) {
            $scope.todos = data;
            // for(var i = 0; i < data.length; i++) {
                //$scope.todos.push(data[i]);
            //}
            $scope.loading = false;
            angular.forEach($scope.todos, function(todo){
                todo.formattedCreatedOn = $filter('date')(new Date(todo.createdOn),'MMM dd, yyyy  -  hh:mm a');
            });
        });

     $scope.$watch('currentPage + numPerPage', function() {
        var begin = (($scope.currentPage - 1) * $scope.numPerPage);
        var end = begin + $scope.numPerPage;

        $scope.filteredTodos = $scope.todos.slice(begin, end);
    });
}]);

$scope.todos,我需要以某种方式将其置于当前范围之外。所以它不适用于function $scope.todos.slice(begin,end)

另一件事是 $watch 函数在 todos 列表构建之前被调用。这是因为当服务从 db 检索待办事项时,$watch 已经在长度为 0 的列表上被调用,因此无法进一步工作。

我什至尝试使用this link 中的代码。

【问题讨论】:

  • 你为什么关注那些变量?我不明白。只需添加一个普通范围方法,一旦您单击分页器指令就会调用该方法。
  • 我按照我刚刚附上的 plunker 链接所示做了。但这并不成功。请帮助我更多。

标签: javascript angularjs pagination slice


【解决方案1】:

我认为你应该通过首先定义 $scope.todos (有一个注释行,为什么它被注释掉?)然后检查边界“开始”和“结束”是否在大小范围内来让它工作你的 todos 数组。您可能会收到一些不能被您的 numPerPage 整除的元素,因此在任何情况下您都必须检查 end 是否超出了数组的大小,如果超出,请进行相应的设置。

$scope.$watch('currentPage + numPerPage', function() {
    var begin = (($scope.currentPage - 1) * $scope.numPerPage);
    var end = begin + $scope.numPerPage;

    if(end>=$scope.todos.length)
      end = $scope.todos.length-1;

    $scope.filteredTodos = $scope.todos.slice(begin, end);
});

让我知道这是否成功。

干杯,克里斯托夫

【讨论】:

  • 好的,发生了什么事?它是否还在抱怨 $scope.todos 在 $scope.watch 中未定义?
  • 不,它并没有抱怨我。但它根本不显示任何记录,只显示分页内容,例如:First Previous 1 Next Last。就是这样。
  • 我猜这是因为 currentPage + numPerPage 在检索数据后不会改变(这是异步的)。您是否尝试从您的用户界面更改这些参数?也许安装 ng-inspector for chrome 来查看你的范围。
【解决方案2】:

如果您显示待办事项列表,我认为您的模板中有一个 ng-repeat。您可能对 limitTo 过滤器感兴趣,这是一种出于显示目的过滤数据的首选方式:

https://docs.angularjs.org/api/ng/filter/limitTo

示例:

angular.module('myApp',[]).controller('TodosController',
function TodosController($scope) {
 $scope.todos = [
  {name:"todo1"},
  {name:"todo2"},
  {name:"todo3"},
  {name:"todo4"},
  {name:"todo5"},
  {name:"todo6"},
  {name:"todo7"}
 ];
  
 /* Rows per page */
 $scope.limit = 3;
 /* We start displaying at item 0 */
 $scope.begin = 0;
}
                                      
);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

<div ng-app="myApp" ng-controller="TodosController">
  
 todos (page {{begin/limit}}):
 <ul>
   <li ng-repeat="todo in todos | limitTo:limit : begin">{{todo}}</li>
 </ul>

 <button ng-click="begin = 0">&lt;&lt;</button>
 <button ng-click="begin = begin>=limit ? begin - limit:0">&lt; previous page</button>
 <button ng-click="begin = begin + limit">next page &gt; </button>
</div>

【讨论】:

  • 这里会超出我的待办事项的限制,不是吗?就像考虑您的案例本身一样,有 7 个待办事项,每个 2 页 5 个。如果我尝试进入下一页,它不会显示任何内容,对吗?如果我错了纠正我。如果是这样,如何阻止它?
  • 我不确定我是否理解您的问题。这只是一个不完整的分页系统“LimitTo”的演示。我会稍微编辑一下。不管怎样,使用limitTo,你可以通过修改'begin'模型来建立你自己的分页系统。
  • 我试过这种方式,如你所见。但它只是在这里更改页码:todos (page 0),而不是它在页面上显示的记录。也就是点击next和previous时,只有页码在变化,列表中的记录没有变化。
  • Chrome 45.0.2454.101 或 FF42 对我来说效果很好:如果我点击“下一页”,我会得到:todos (page 1): {"name":"todo4"} {"name":"todo5"} {"name":"todo6"}
  • 我已经编辑了示例,因此您无法转到显示奇怪行为的否定页面
【解决方案3】:

我添加了以下代码:

todoApp.filter('limitFromTo', function(){
    return function(input, from, to){
        return (input != undefined)? input.slice(from, to) : '';
    }
});

并在这里使用了这个过滤器:

ng-repeat="todo in todos | limitFromTo:(currentPage-1)*itemsPerPage:(currentPage*itemsPerPage)"

我没有使用使用itemsPerPage(currentPage-1)*itemsPerPage 等参数的limitTo 函数,而是使用了我自己的过滤器limitFromTo,它在数组中将有两个偏移量,就像currentPage 是1然后它将显示 0-5 的记录,2 6-10 的记录,依此类推。 limitTo 过滤器具有要显示多少条记录从哪个索引或偏移量等参数,这不是我想要的,因此根据我的需要使用了 limitFromTo。它奏效了。

【讨论】:

    【解决方案4】:

    尝试将$scope.$watch 放在.success 回调中:

    Todos.get()
        .success(function(data) {
    
            $scope.$watch('currentPage + numPerPage', function() {
              var begin = (($scope.currentPage - 1) * $scope.numPerPage);
              var end = begin + $scope.numPerPage;
    
              $scope.filteredTodos = data.slice(begin, end);
            });
        });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-08
      • 1970-01-01
      • 2015-09-14
      • 2021-07-16
      • 2013-09-12
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      相关资源
      最近更新 更多