【问题标题】:How to do paging in AngularJS?如何在 AngularJS 中进行分页?
【发布时间】:2012-06-04 16:13:00
【问题描述】:

我在内存中有大约 1000 个项目的数据集,我正在尝试为 这个数据集,但我不确定如何执行此操作。

我正在使用自定义过滤器功能来过滤结果,效果很好,但不知何故我需要得到页数。

有什么线索吗?

【问题讨论】:

    标签: angularjs pagination


    【解决方案1】:

    以下代码将有助于在后端提供带有角度重复的自定义分页。

    您的数据将在

    $scope.myticketIssuesData = [];
    $scope.allticketIssuesData = [];
    

    var jiraapp = angular.module('jiraapp',  ['ui.bootstrap']);
    
    jiraapp.controller('JiraController', ['$scope', '$http', '$window','$location', function JiraController($scope, $http, $window,$location) {
        
        $scope.myticketIssuesData = [];
        $scope.allticketIssuesData = [];
        $scope.jiraIssue = {};
        $scope.RequesterType = [];
        $scope.loading = false;
        $scope.showerror = false;
        $scope.alert = {};
    
        $scope.maxSize = 10;    
        $scope.totalCount = 0;  
        $scope.pageIndex = 0;  
        $scope.startIndex = 0;
        $scope.pageSizeSelected = 10;
    
        $scope.maxallSize = 10;
        $scope.totalallCount = 0;
        $scope.pageallIndex = 0; 
        $scope.startallIndex = 0;
        $scope.pageallSizeSelected = 10;
    
        $scope.getUserTickets = function()  {
            $scope.loading = true;
            $http({
                method: 'GET',
                url: 'http://localhost:53583/api/Jira/getUserTickets?assignee='+$scope.loc+'&startAt='+ $scope.startIndex +'&maxResults='+$scope.pageSizeSelected,
                headers: {
                    "Accept": "application/json",
                    "Access-Control-Allow-Origin": "http://localhost:8080",
                    "crossDomain": "true",
                }
            }).then(function successCallback(response) {
                
                $scope.myticketIssuesData = response.data.issues;
                $scope.totalCount = response.data.total;
                
                $scope.loading = false;
               
            }, function errorCallback(response) {
                $scope.loading = false;
               
            });
        }
        
        $scope.getrequestType = function(){
            $http({
                method: 'GET',
                url: 'http://localhost:53583/api/Jira/getrequestType',
                headers: {
                    "Accept": "application/json",
                    "Access-Control-Allow-Origin": "http://localhost:8080",
                    "crossDomain": "true",
                }
            }).then(function successCallback(response) {
                $scope.RequesterType = response.data.values;
            }, function errorCallback(response) {
            });
        }
    
        $scope.getDropDown = function(){
            $scope.getrequestType();
        }
    
        $scope.initialize = function (item) {
            $scope.getUserTickets();
            $scope.getDropDown();
        }
    
        $scope.initialize();
    
        $scope.pageChanged = function () {  
    
            if($scope.pageIndex == 0)
                $scope.startIndex = 0;
            else if($scope.pageIndex == 1)
                $scope.startIndex = 0;
            else
                $scope.startIndex =  (($scope.pageIndex-1) * $scope.pageSizeSelected);
    
            $scope.getUserTickets();
        };  
    
        $scope.pageallChanged = function () {  
    
            if($scope.pageallIndex == 0)
                $scope.startallIndex = 0;
            else if($scope.pageallIndex == 1)
                $scope.startallIndex = 0;
            else
                $scope.startallIndex =  (($scope.pageallIndex-1) * $scope.pageallSizeSelected);
            $scope.getAllTickets();
        };  
    
        $scope.changeallPageSize = function () {  
            $scope.pageallIndex = 0;  
            $scope.getAllTickets();
        };  
    
        $scope.getAllTickets = function()  {
            $scope.loading = true;
            $http({
                method: 'GET',
                url: 'http://localhost:53583/api/Jira/getAllTickets?startAt='+ $scope.startallIndex +'&maxResults='+$scope.pageallSizeSelected,
                headers: {
                    "Accept": "application/json",
                    "Access-Control-Allow-Origin": "http://localhost:8080",
                    "crossDomain": "true",
                }
            }).then(function successCallback(response) {
                
                $scope.allticketIssuesData = response.data.issues;
                $scope.totalallCount = response.data.total;
                
                $scope.loading = false;
               
            }, function errorCallback(response) {
                
                $scope.loading = false;
                
    
            });
        }
    
    
    }]);
    <html ng-app="jiraapp">
    
    <head>
        <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        crossorigin="anonymous"></script>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
        <link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro' rel='stylesheet' type='text/css'>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
            crossorigin="anonymous"></script>
    
        <script src="/angular.min.js"></script>
        <script src="/jira.js"></script>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular-route.min.js"></script>
        
        <script src="/ui-bootstrap-tpls-0.13.4.min.js"></script>
    
        <!-- this is important -->
        <style type="text/css">
            #loading {
                position: fixed;
                top: 50%;
                left: 50%;
                margin-top: -5em;
                margin-left: -10em;
            }
    
            .pagination {
                display: inline-block;
                padding-left: 0;
                margin: 20px 0;
                border-radius: 4px
            }
    
            .pagination>li {
                display: inline
            }
    
            .pagination>li>a,
            .pagination>li>span {
                position: relative;
                float: left;
                padding: 6px 12px;
                margin-left: -1px;
                line-height: 1.42857143;
                color: #337ab7;
                text-decoration: none;
                background-color: #fff;
                border: 1px solid #ddd
            }
    
            .pagination>li:first-child>a,
            .pagination>li:first-child>span {
                margin-left: 0;
                border-top-left-radius: 4px;
                border-bottom-left-radius: 4px
            }
    
            .pagination>li:last-child>a,
            .pagination>li:last-child>span {
                border-top-right-radius: 4px;
                border-bottom-right-radius: 4px
            }
    
            .pagination>li>a:focus,
            .pagination>li>a:hover,
            .pagination>li>span:focus,
            .pagination>li>span:hover {
                z-index: 3;
                color: #23527c;
                background-color: #eee;
                border-color: #ddd
            }
    
            .pagination>.active>a,
            .pagination>.active>a:focus,
            .pagination>.active>a:hover,
            .pagination>.active>span,
            .pagination>.active>span:focus,
            .pagination>.active>span:hover {
                z-index: 2;
                color: #fff;
                cursor: default;
                background-color: #337ab7;
                border-color: #337ab7
            }
    
            .pagination>.disabled>a,
            .pagination>.disabled>a:focus,
            .pagination>.disabled>a:hover,
            .pagination>.disabled>span,
            .pagination>.disabled>span:focus,
            .pagination>.disabled>span:hover {
                color: #777;
                cursor: not-allowed;
                background-color: #fff;
                border-color: #ddd
            }
    
            .pagination-lg>li>a,
            .pagination-lg>li>span {
                padding: 10px 16px;
                font-size: 18px;
                line-height: 1.3333333
            }
    
            .pagination-lg>li:first-child>a,
            .pagination-lg>li:first-child>span {
                border-top-left-radius: 6px;
                border-bottom-left-radius: 6px
            }
    
            .pagination-lg>li:last-child>a,
            .pagination-lg>li:last-child>span {
                border-top-right-radius: 6px;
                border-bottom-right-radius: 6px
            }
    
            .pagination-sm>li>a,
            .pagination-sm>li>span {
                padding: 5px 10px;
                font-size: 12px;
                line-height: 1.5
            }
    
            .pagination-sm>li:first-child>a,
            .pagination-sm>li:first-child>span {
                border-top-left-radius: 3px;
                border-bottom-left-radius: 3px
            }
    
            .pagination-sm>li:last-child>a,
            .pagination-sm>li:last-child>span {
                border-top-right-radius: 3px;
                border-bottom-right-radius: 3px
            }
    
            .pager {
                padding-left: 0;
                margin: 20px 0;
                text-align: center;
                list-style: none
            }
    
            .pager li {
                display: inline
            }
    
            .pager li>a,
            .pager li>span {
                display: inline-block;
                padding: 5px 14px;
                background-color: #fff;
                border: 1px solid #ddd;
                border-radius: 15px
            }
    
            .pager li>a:focus,
            .pager li>a:hover {
                text-decoration: none;
                background-color: #eee
            }
    
            .pager .next>a,
            .pager .next>span {
                float: right
            }
    
            .pager .previous>a,
            .pager .previous>span {
                float: left
            }
    
            .pager .disabled>a,
            .pager .disabled>a:focus,
            .pager .disabled>a:hover,
            .pager .disabled>span {
                color: #777;
                cursor: not-allowed;
                background-color: #fff
            }
        </style>
    </head>
    
    <body ng-controller="JiraController">
        <div class="col-sm-12">
            <div class="row" style="background: #09c;">
                <div style="margin-left: auto; margin-right: auto;">
                    <img src="/logo.png" height="80">
                    <span class="d-none d-sm-inline"
                        style="color: white; font-size: 4rem; vertical-align: middle; font-family:'Source Code Pro'">Jira</span>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-12">
                    <nav>
                        <div class="nav nav-tabs" id="nav-tab" role="tablist">
                            <a class="nav-item nav-link active" id="nav-myticket-tab" data-toggle="tab" href="#nav-myticket"
                                role="tab" aria-controls="nav-myticket" aria-selected="true" ng-click="getUserTickets()">My
                                Ticket</a>
                        </div>
                    </nav>
                    <div class="tab-content" id="nav-tabContent">
                        <div class="tab-pane fade show active" id="nav-myticket" role="tabpanel"
                            aria-labelledby="nav-myticket-tab">
                            <div class="col-sm-12" style="margin:10px">
                                <div id="loading" ng-show="loading">
                                    <img src="spinner.gif">
                                </div>
                                    <table ng-show="!loading"  class="table table-striped table-bordered table-hover tabel-condensed">
                                        <thead>
                                            <tr>
                                                <td>Key</td>
                                                <td>Priority</td>
                                                <td>Summary</td>
                                                <td>Assignee</td>
                                                <td>Status</td>
                                                <td>Due Date</td>
                                            </tr>
                                        </thead>
                                        <tbody>
                                            <tr ng-repeat="data in myticketIssuesData">
                                                <td>
                                                    <a href={{data.fields.customfield_10023._links.web}} target="_blank">
                                                        {{data.key}}
                                                    </a>
                                                </td>
                                                <td>{{data.fields.priority.name}}</td>
                                                <td>{{data.fields.summary}}</td>
                                                <td>{{data.fields.assignee.displayName}}</td>
                                                <td>{{data.fields.status.name}}</td>
                                                <td>{{data.fields.duedate}}</td>
                                            </tr>
                                        </tbody>
                                        <tfoot>
                                            <tr>
                                                <td align="center" colspan="6">
                                                    <!-- <span class="form-group pull-left page-size form-inline">
                                                        <select id="ddlPageSize" class="form-control control-color"
                                                            ng-model="pageSizeSelected" ng-change="changePageSize()">
                                                            <option value="5">5</option>
                                                            <option value="10">10</option>
                                                            <option value="25">25</option>
                                                            <option value="50">50</option>
                                                        </select>
                                                    </span> -->
                                                    <div class="pull-right">
                                                        <pagination total-items="totalCount" ng-change="pageChanged()"
                                                            items-per-page="pageSizeSelected" direction-links="true"
                                                            ng-model="pageIndex" max-size="maxSize" class="pagination"
                                                            boundary-links="true" rotate="false" num-pages="numPages">
                                                        </pagination>
                                                        <a style="margin-left: 640px;" class="btn btn-primary">Page: {{pageIndex}} / {{numPages}}</a>
                                                    </div>
                                                </td>
                                            </tr>
                                        </tfoot>
                                    </table>
                            </div>
                        </div>
    
                    </div>
    
                </div>
            </div>
    </body>
    
    </html>

    【讨论】:

      【解决方案2】:

      您可以使用 Bootstrap UI 指令轻松完成此操作。

      这个答案是对@Scotty.NET 给出的答案的修改,我已经更改了代码,因为&lt;pagination&gt; 指令现在已被弃用。

      以下代码生成分页:

      <ul uib-pagination 
          boundary-links="true"  
          total-items="totalItems"  
          items-per-page="itemsPerPage"  
          ng-model="currentPage"  
          ng-change="pageChanged()"  
          class="pagination"  
          previous-text="&lsaquo;"  
          next-text="&rsaquo;"  
          first-text="&laquo;"  
          last-text="&raquo;">
      </ul>
      

      要使其正常运行,请在您的控制器中使用它:

      $scope.filteredData = []
      $scope.totalItems = $scope.data.length;
      $scope.currentPage = 1;
      $scope.itemsPerPage = 5;
      
      $scope.setPage = function (pageNo) {
          $scope.currentPage = pageNo;
      };
      
      $scope.pageChanged = function() {
          var begin = (($scope.currentPage - 1) * $scope.itemsPerPage)
          , end = begin + $scope.itemsPerPage;
      
          $scope.filteredData = $scope.data.slice(begin, end);
      };
      
      $scope.pageChanged();
      

      更多分页选项请参考:Bootstrap UI Pagination Directive

      【讨论】:

        【解决方案3】:

        从 Angular 1.4 开始,limitTo 过滤器还接受第二个可选参数 begin

        来自docs

        {{ limitTo_expression | limitTo : limit : 开始}}

        开始 (可选的) 字符串|数字
        开始限制的索引。作为负索引,begin 表示从输入结尾的偏移量。默认为 0。

        所以不需要新建指令,这个参数可以用来设置分页的偏移量

        ng-repeat="item in vm.items| limitTo: vm.itemsPerPage: (vm.currentPage-1)*vm.itemsPerPage" 
        

        【讨论】:

          【解决方案4】:

          下面的解决方案很简单。

          <pagination  
                  total-items="totalItems" 
                  items-per-page= "itemsPerPage"
                  ng-model="currentPage" 
                  class="pagination-sm">
          </pagination>
          
          <tr ng-repeat="country in countries.slice((currentPage -1) * itemsPerPage, currentPage * itemsPerPage) "> 
          

          Here is sample jsfiddle

          【讨论】:

            【解决方案5】:

            我想添加适用于 ngRepeat 的解决方案和您使用的过滤器,而不使用 $watch 或切片数组。

            您的过滤结果将被分页!

            var app = angular.module('app', ['ui.bootstrap']);
            
            app.controller('myController', ['$scope', function($scope){
                $scope.list= ['a', 'b', 'c', 'd', 'e'];
            
                $scope.pagination = {
                    currentPage: 1,
                    numPerPage: 5,
                    totalItems: 0
                };
            
                $scope.searchFilter = function(item) {
                    //Your filter results will be paginated!
                    //The pagination will work even with other filters involved
                    //The total number of items in the result of your filter is accounted for
                };
            
                $scope.paginationFilter = function(item, index) {
                    //Every time the filter is used it restarts the totalItems
                    if(index === 0) 
                        $scope.pagination.totalItems = 0;
            
                    //This holds the totalItems after the filters are applied
                    $scope.pagination.totalItems++;
            
                    if(
                        index >= (($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage)
                        && index < ((($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage) + $scope.pagination.numPerPage)
                    )
                        return true; //return true if item index is on the currentPage
            
                    return false;
                };
            }]);
            

            确保在 HTML 中将过滤器应用到 ngRepeat 分页过滤器之前。

            <table data-ng-controller="myController">
                <tr data-ng-repeat="item in list | filter: searchFilter | filter: paginationFilter track by $index">
                    <td>
                        {{item}}
                    </td>
                <tr>
            </table>
            <ul class="pagination-sm"
                uib-pagination
                data-boundary-links="true"
                data-total-items="pagination.totalItems"
                data-items-per-page="pagination.numPerPage"
                data-ng-model="pagination.currentPage"
                data-previous-text="&lsaquo;"
                data-next-text="&rsaquo;"
                data-first-text="&laquo;"
                data-last-text="&raquo;">
             </ul>
            

            【讨论】:

              【解决方案6】:

              ng-重复分页

                  <div ng-app="myApp" ng-controller="MyCtrl">
              <input ng-model="q" id="search" class="form-control" placeholder="Filter text">
              <select ng-model="pageSize" id="pageSize" class="form-control">
                  <option value="5">5</option>
                  <option value="10">10</option>
                  <option value="15">15</option>
                  <option value="20">20</option>
               </select>
              <ul>
                  <li ng-repeat="item in data | filter:q | startFrom:currentPage*pageSize | limitTo:pageSize">
                      {{item}}
                  </li>
              </ul>
              <button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
                  Previous
              </button>
              {{currentPage+1}}/{{numberOfPages()}}
               <button ng-disabled="currentPage >= getData().length/pageSize - 1" ng-                 click="currentPage=currentPage+1">
                  Next
                  </button>
              </div>
              
              <script>
              
               var app=angular.module('myApp', []);
              
               app.controller('MyCtrl', ['$scope', '$filter', function ($scope, $filter) {
               $scope.currentPage = 0;
               $scope.pageSize = 10;
               $scope.data = [];
               $scope.q = '';
              
               $scope.getData = function () {
              
                return $filter('filter')($scope.data, $scope.q)
              
                 }
              
                 $scope.numberOfPages=function(){
                  return Math.ceil($scope.getData().length/$scope.pageSize);                
                 }
              
                 for (var i=0; i<65; i++) {
                  $scope.data.push("Item "+i);
                 }
                }]);
              
                      app.filter('startFrom', function() {
                  return function(input, start) {
                  start = +start; //parse to int
                  return input.slice(start);
                 }
                });
                </script>
              

              【讨论】:

                【解决方案7】:

                老问题,但由于我认为我的方法有点不同且不那么复杂,我将分享这个问题,并希望除我之外的其他人发现它有用。

                我发现简单而小型的分页解决方案是将指令与使用相同范围变量的过滤器结合起来。

                要实现这一点,您可以在数组上添加过滤器并像这样添加指令

                <div class="row">
                    <table class="table table-hover">
                        <thead>
                            <tr>
                                <th>Name</th>
                                <th>Price</th>
                                <th>Quantity</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr ng-repeat="item in items | cust_pagination:p_Size:p_Step">
                                <td>{{item.Name}}</td>
                                <td>{{item.Price}}</td>
                                <td>{{item.Quantity}}</td>
                            </tr>
                        </tbody>
                    </table>
                    <div cust-pagination p-items="items" p-boundarylinks="true" p-size="p_Size" p-step="p_Step"></div>
                </div>
                

                p_Size 和 p_Step 是范围变量,可以在范围内自定义,否则 p_Size 的默认值为 5,p_Step 为 1。

                当分页中的步骤发生变化时,p_Step 会更新,并将触发 cust_pagination 过滤器的新过滤。 cust_pagination 过滤器然后根据 p_Step 值对数组进行切片,如下所示,仅返回在分页部分中选择的活动记录

                var startIndex = nStep * nPageSize;
                var endIndex = startIndex + nPageSize;
                var arr = items.slice(startIndex, endIndex);
                return arr;
                

                演示 View the complete solution in this plunker

                【讨论】:

                  【解决方案8】:

                  Angular-Paging

                  是个不错的选择

                  一个指令,用于帮助对大型数据集进行分页,同时需要最少的实际分页信息。在这种分页方案中,我们非常依赖服务器来“过滤”结果。中心思想是我们只想保存项目的活动“页面” - 而不是将整个项目列表保存在内存中并在客户端进行分页。

                  【讨论】:

                    【解决方案9】:

                    概览分页使用

                     - ng-repeat
                     - uib-pagination
                    

                    查看

                    <div class="row">
                        <div class="col-lg-12">
                            <table class="table">
                                <thead style="background-color: #eee">
                                    <tr>
                                        <td>Dispature</td>
                                        <td>Service</td>
                                        <td>Host</td>
                                        <td>Value</td>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr ng-repeat="x in app.metricsList">
                                        <td>{{x.dispature}}</td>
                                        <td>{{x.service}}</td>
                                        <td>{{x.host}}</td>
                                        <td>{{x.value}}</td>
                                    </tr>
                                </tbody>
                            </table>
                    
                            <div align="center">
                                <uib-pagination items-per-page="app.itemPerPage" num-pages="numPages"
                                    total-items="app.totalItems" boundary-link-numbers="true"
                                    ng-model="app.currentPage" rotate="false" max-size="app.maxSize"
                                    class="pagination-sm" boundary-links="true"
                                    ng-click="app.getPagableRecords()"></uib-pagination>        
                    
                                <div style="float: right; margin: 15px">
                                    <pre>Page: {{app.currentPage}} / {{numPages}}</pre>
                                </div>          
                            </div>
                        </div>
                    </div>
                    

                    JS 控制器

                    app.controller('AllEntryCtrl',['$scope','$http','$timeout','$rootScope', function($scope,$http,$timeout,$rootScope){
                    
                        var app = this;
                        app.currentPage = 1;
                        app.maxSize = 5;
                        app.itemPerPage = 5;
                        app.totalItems = 0;
                    
                        app.countRecords = function() {
                            $http.get("countRecord")
                            .success(function(data,status,headers,config){
                                app.totalItems = data;
                            })
                            .error(function(data,status,header,config){
                                console.log(data);
                            });
                        };
                    
                        app.getPagableRecords = function() {
                            var param = {
                                    page : app.currentPage,
                                    size : app.itemPerPage  
                            };
                            $http.get("allRecordPagination",{params : param})
                            .success(function(data,status,headers,config){
                                app.metricsList = data.content;
                            })
                            .error(function(data,status,header,config){
                                console.log(data);
                            });
                        };
                    
                        app.countRecords();
                        app.getPagableRecords();
                    
                    }]);
                    

                    【讨论】:

                      【解决方案10】:

                      这是一个纯 javascript 解决方案,我已将其包装为 Angular 服务来实现分页逻辑,例如在 google 搜索结果中。

                      http://codepen.io/cornflourblue/pen/KVeaQL/CodePen 上的工作演示

                      详情及解释this blog post

                      function PagerService() {
                          // service definition
                          var service = {};
                      
                          service.GetPager = GetPager;
                      
                          return service;
                      
                          // service implementation
                          function GetPager(totalItems, currentPage, pageSize) {
                              // default to first page
                              currentPage = currentPage || 1;
                      
                              // default page size is 10
                              pageSize = pageSize || 10;
                      
                              // calculate total pages
                              var totalPages = Math.ceil(totalItems / pageSize);
                      
                              var startPage, endPage;
                              if (totalPages <= 10) {
                                  // less than 10 total pages so show all
                                  startPage = 1;
                                  endPage = totalPages;
                              } else {
                                  // more than 10 total pages so calculate start and end pages
                                  if (currentPage <= 6) {
                                      startPage = 1;
                                      endPage = 10;
                                  } else if (currentPage + 4 >= totalPages) {
                                      startPage = totalPages - 9;
                                      endPage = totalPages;
                                  } else {
                                      startPage = currentPage - 5;
                                      endPage = currentPage + 4;
                                  }
                              }
                      
                              // calculate start and end item indexes
                              var startIndex = (currentPage - 1) * pageSize;
                              var endIndex = startIndex + pageSize;
                      
                              // create an array of pages to ng-repeat in the pager control
                              var pages = _.range(startPage, endPage + 1);
                      
                              // return object with all pager properties required by the view
                              return {
                                  totalItems: totalItems,
                                  currentPage: currentPage,
                                  pageSize: pageSize,
                                  totalPages: totalPages,
                                  startPage: startPage,
                                  endPage: endPage,
                                  startIndex: startIndex,
                                  endIndex: endIndex,
                                  pages: pages
                              };
                          }
                      }
                      

                      【讨论】:

                      • 我使用了你的方法,但问题是如果我想使用 index-es 在页面上进行排序,它总是显示为 0-9...
                      【解决方案11】:

                      我使用这个第 3 方分页库,它运行良好。它可以做本地/远程数据源,而且非常可配置。

                      https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination

                      <dir-pagination-controls
                          [max-size=""]
                          [direction-links=""]
                          [boundary-links=""]
                          [on-page-change=""]
                          [pagination-id=""]
                          [template-url=""]
                          [auto-hide=""]>
                          </dir-pagination-controls>
                      

                      【讨论】:

                        【解决方案12】:

                        我希望我可以发表评论,但我只需要在这里留下这个:

                        Scotty.NET 的回答和 user2176745 对更高版本的重做都很棒,但它们都错过了我的 AngularJS (v1.3.15) 版本中断的东西:

                        i 未在 $scope.makeTodos 中定义。

                        因此,用这个函数替换它可以修复更新的 Angular 版本。

                        $scope.makeTodos = function() {
                            var i;
                            $scope.todos = [];
                            for (i=1;i<=1000;i++) {
                                $scope.todos.push({ text:'todo '+i, done:false});
                            }
                        };
                        

                        【讨论】:

                          【解决方案13】:

                          对于像我这样难以为表格创建分页器的人,我发布了这个。 所以,在你看来:

                                    <pagination total-items="total" items-per-page="itemPerPage"    ng-model="currentPage" ng-change="pageChanged()"></pagination>    
                                  <!-- To specify your choice of items Per Pages-->
                               <div class="btn-group">
                                          <label class="btn btn-primary" ng-model="radioModel"  btn-radio="'Left'" data-ng-click="setItems(5)">5</label>
                                          <label class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'" data-ng-click="setItems(10)">10</label>
                                          <label class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'" data-ng-click="setItems(15)">15</label>
                                      </div>
                               //And don't forget in your table:
                                <tr data-ng-repeat="p in profiles | offset: (currentPage-1)*itemPerPage | limitTo: itemPerPage" >
                          

                          在你的 angularJs 中:

                            var module = angular.module('myapp',['ui.bootstrap','dialogs']);
                            module.controller('myController',function($scope,$http){
                             $scope.total = $scope.mylist.length;     
                             $scope.currentPage = 1;
                             $scope.itemPerPage = 2;
                             $scope.start = 0;
                          
                             $scope.setItems = function(n){
                                   $scope.itemPerPage = n;
                             };
                             // In case you can replace ($scope.currentPage - 1) * $scope.itemPerPage in <tr> by "start"
                             $scope.pageChanged = function() {
                                  $scope.start = ($scope.currentPage - 1) * $scope.itemPerPage;
                                      };  
                          });
                             //and our filter
                               module.filter('offset', function() {
                                        return function(input, start) {
                                          start = parseInt(start, 10);
                                          return input.slice(start);
                                        };
                                      });     
                          

                          【讨论】:

                          • 有很多赞成和肯定的答案..但没有一个对我有用..但是这个结合@svarog的答案对我来说就像一个魅力。
                          【解决方案14】:

                          Angular UI Bootstrap - 分页指令

                          查看UI Bootstrappagination directive。我最终使用了它,而不是这里发布的内容,因为它有足够的功能供我当前使用,并且有一个 thorough test spec 来陪伴它。

                          查看

                          <!-- table here -->
                          
                          <pagination 
                            ng-model="currentPage"
                            total-items="todos.length"
                            max-size="maxSize"  
                            boundary-links="true">
                          </pagination>
                          
                          <!-- items/page select here if you like -->
                          

                          控制器

                          todos.controller("TodoController", function($scope) {
                             $scope.filteredTodos = []
                            ,$scope.currentPage = 1
                            ,$scope.numPerPage = 10
                            ,$scope.maxSize = 5;
                          
                            $scope.makeTodos = function() {
                              $scope.todos = [];
                              for (i=1;i<=1000;i++) {
                                $scope.todos.push({ text:"todo "+i, done:false});
                              }
                            };
                            $scope.makeTodos(); 
                          
                            $scope.$watch("currentPage + numPerPage", function() {
                              var begin = (($scope.currentPage - 1) * $scope.numPerPage)
                              , end = begin + $scope.numPerPage;
                          
                              $scope.filteredTodos = $scope.todos.slice(begin, end);
                            });
                          });
                          

                          我发了working plunker供参考。


                          旧版:

                          查看

                          <!-- table here -->
                          
                          <div data-pagination="" data-num-pages="numPages()" 
                            data-current-page="currentPage" data-max-size="maxSize"  
                            data-boundary-links="true"></div>
                          
                          <!-- items/page select here if you like -->
                          

                          控制器

                          todos.controller("TodoController", function($scope) {
                             $scope.filteredTodos = []
                            ,$scope.currentPage = 1
                            ,$scope.numPerPage = 10
                            ,$scope.maxSize = 5;
                          
                            $scope.makeTodos = function() {
                              $scope.todos = [];
                              for (i=1;i<=1000;i++) {
                                $scope.todos.push({ text:"todo "+i, done:false});
                              }
                            };
                            $scope.makeTodos(); 
                          
                            $scope.numPages = function () {
                              return Math.ceil($scope.todos.length / $scope.numPerPage);
                            };
                          
                            $scope.$watch("currentPage + numPerPage", function() {
                              var begin = (($scope.currentPage - 1) * $scope.numPerPage)
                              , end = begin + $scope.numPerPage;
                          
                              $scope.filteredTodos = $scope.todos.slice(begin, end);
                            });
                          });
                          

                          我发了working plunker供参考。

                          【讨论】:

                          • 漂亮优雅。可以通过添加排序来改进
                          • 不再需要 num-pages 属性并且是只读的。无需传递 numPages。请参阅文档:angular-ui.github.io/bootstrap/#/pagination
                          • 已解决: items-per-page 是需要在pagination 元素中设置的属性。
                          • ^^^^ 对于所有新读者,请参阅 Bogacs 评论:分页元素中现在需要每页项目。没有它就不行。
                          • 现在已弃用。请改用
                          【解决方案15】:

                          我在这里提取了相关的部分。这是一个“简洁”的表格分页器,因此不包括排序或过滤。根据需要随意更改/添加:

                               //your data source may be different. the following line is 
                               //just for demonstration purposes only
                              var modelData = [{
                                text: 'Test1'
                              }, {
                                text: 'Test2'
                              }, {
                                text: 'Test3'
                              }];
                          
                              (function(util) {
                          
                                util.PAGE_SIZE = 10;
                          
                                util.range = function(start, end) {
                                  var rng = [];
                          
                                  if (!end) {
                                    end = start;
                                    start = 0;
                                  }
                          
                                  for (var i = start; i < end; i++)
                                    rng.push(i);
                          
                                  return rng;
                                };
                          
                                util.Pager = function(data) {
                                  var self = this,
                                    _size = util.PAGE_SIZE;;
                          
                                  self.current = 0;
                          
                                  self.content = function(index) {
                                    var start = index * self.size,
                                      end = (index * self.size + self.size) > data.length ? data.length : (index * self.size + self.size);
                          
                                    return data.slice(start, end);
                                  };
                          
                                  self.next = function() {
                                    if (!self.canPage('Next')) return;
                                    self.current++;
                                  };
                          
                                  self.prev = function() {
                                    if (!self.canPage('Prev')) return;
                                    self.current--;
                                  };
                          
                                  self.canPage = function(dir) {
                                    if (dir === 'Next') return self.current < self.count - 1;
                                    if (dir === 'Prev') return self.current > 0;
                                    return false;
                                  };
                          
                                  self.list = function() {
                                    var start, end;
                                    start = self.current < 5 ? 0 : self.current - 5;
                                    end = self.count - self.current < 5 ? self.count : self.current + 5;
                                    return Util.range(start, end);
                                  };
                          
                                  Object.defineProperty(self, 'size', {
                                    configurable: false,
                                    enumerable: false,
                                    get: function() {
                                      return _size;
                                    },
                                    set: function(val) {
                                      _size = val || _size;
                                    }
                                  });
                          
                                  Object.defineProperty(self, 'count', {
                                    configurable: false,
                                    enumerable: false,
                                    get: function() {
                                      return Math.ceil(data.length / self.size);
                                    }
                                  });
                                };
                          
                              })(window.Util = window.Util || {});
                          
                              (function(ns) {
                                ns.SampleController = function($scope, $window) {
                                  $scope.ModelData = modelData;
                                  //instantiate pager with array (i.e. our model)
                                  $scope.pages = new $window.Util.Pager($scope.ModelData);
                                };
                              })(window.Controllers = window.Controllers || {});
                          <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
                          <table ng-controller="Controllers.SampleController">
                            <thead>
                              <tr>
                                <th>
                                  Col1
                                </th>
                              </tr>
                            </thead>
                            <tbody>
                              <tr ng-repeat="item in pages.content(pages.current)" title="{{item.text}}">
                                <td ng-bind-template="{{item.text}}"></td>
                              </tr>
                            </tbody>
                            <tfoot>
                              <tr>
                                <td colspan="4">
                                  <a href="#" ng-click="pages.prev()">&laquo;</a>
                                  <a href="#" ng-repeat="n in pages.list()" ng-click="pages.current = n" style="margin: 0 2px;">{{n + 1}}</a>
                                  <a href="#" ng-click="pages.next()">&raquo;</a>
                                </td>
                              </tr>
                            </tfoot>
                          </table>

                          【讨论】:

                            【解决方案16】:

                            我更新了 Scotty.NET's plunkr http://plnkr.co/edit/FUeWwDu0XzO51lyLAEIA?p=preview 以便它使用更新版本的 angular、angular-ui 和 bootstrap。

                            控制器

                            var todos = angular.module('todos', ['ui.bootstrap']);
                            
                            todos.controller('TodoController', function($scope) {
                              $scope.filteredTodos = [];
                              $scope.itemsPerPage = 30;
                              $scope.currentPage = 4;
                            
                              $scope.makeTodos = function() {
                                $scope.todos = [];
                                for (i=1;i<=1000;i++) {
                                  $scope.todos.push({ text:'todo '+i, done:false});
                                }
                              };
                            
                              $scope.figureOutTodosToDisplay = function() {
                                var begin = (($scope.currentPage - 1) * $scope.itemsPerPage);
                                var end = begin + $scope.itemsPerPage;
                                $scope.filteredTodos = $scope.todos.slice(begin, end);
                              };
                            
                              $scope.makeTodos(); 
                              $scope.figureOutTodosToDisplay();
                            
                              $scope.pageChanged = function() {
                                $scope.figureOutTodosToDisplay();
                              };
                            
                            });
                            

                            引导界面组件

                             <pagination boundary-links="true" 
                                max-size="3" 
                                items-per-page="itemsPerPage"
                                total-items="todos.length" 
                                ng-model="currentPage" 
                                ng-change="pageChanged()"></pagination>
                            

                            【讨论】:

                            • 这个更新的解决方案确实满足了我的需求。非常感谢。
                            【解决方案17】:

                            这是我的例子。列表中间的选中按钮 控制器。 配置 >>>

                             $scope.pagination = {total: null, pages: [], config: {count: 10, page: 1, size: 7}};
                            

                            分页逻辑:

                            /*
                                 Pagination
                                 */
                                $scope.$watch('pagination.total', function (total) {
                                    if(!total || total <= $scope.pagination.config.count) return;
                                    _setPaginationPages(total);
                                });
                            
                                function _setPaginationPages(total) {
                                    var totalPages = Math.ceil(total / $scope.pagination.config.count);
                                    var pages = [];
                                    var start = $scope.pagination.config.page - Math.floor($scope.pagination.config.size/2);
                                    var finish = null;
                            
                                    if((start + $scope.pagination.config.size - 1) > totalPages){
                                        start = totalPages - $scope.pagination.config.size;
                                    }
                                    if(start <= 0) {
                                        start = 1;
                                    }
                            
                                   finish = start +  $scope.pagination.config.size - 1;
                                   if(finish > totalPages){
                                       finish = totalPages;
                                   }
                            
                            
                                    for (var i = start; i <= finish; i++) {
                                        pages.push(i);
                                    }
                            
                                    $scope.pagination.pages = pages;
                                }
                            
                                $scope.$watch("pagination.config.page", function(page){
                                    _setPaginationPages($scope.pagination.total);
                                    _getRespondents($scope.pagination.config);
                                });
                            

                            以及我对引导程序的看法

                            <ul ng-class="{hidden: pagination.total == 0}" class="pagination">
                                    <li ng-click="pagination.config.page = pagination.config.page - 1"
                                        ng-class="{disabled: pagination.config.page == 1}" ><a href="#">&laquo;</a></li>
                                    <li ng-repeat="p in pagination.pages"
                                        ng-click="pagination.config.page = p"
                                        ng-class="{active: p == pagination.config.page}"><a href="#">{{p}}</a></li>
                                    <li ng-click="pagination.config.page = pagination.config.page + 1"
                                        ng-class="{disabled: pagination.config.page == pagination.pages.length}"><a href="#">&raquo;</a></li>
                                </ul >
                            

                            很有用

                            【讨论】:

                              【解决方案18】:

                              我不得不多次使用 Angular 实现分页,对于我认为可以简化的东西总是有点痛苦。我使用了这里和其他地方提出的一些想法来制作一个分页模块,使分页变得如此简单:

                              <ul>
                                  <li dir-paginate="item in items | itemsPerPage: 10">{{ item }}</li>
                              </ul>
                              
                              // then somewhere else on the page ....
                              
                              <dir-pagination-controls></dir-pagination-controls>
                              

                              就是这样。它具有以下特点:

                              • 无需在控制器中使用自定义代码即可将集合 items 绑定到分页链接。
                              • 您不必使用表格或网格视图 - 您可以对任何可以重复的内容进行分页!
                              • 委托给ng-repeat,因此您可以使用可以在ng-repeat 中有效使用的任何表达式,包括过滤、排序等。
                              • 跨控制器工作 - pagination-controls 指令不需要了解调用 paginate 指令的上下文。

                              演示:http://plnkr.co/edit/Wtkv71LIqUR4OhzhgpqL?p=preview

                              对于那些正在寻找“即插即用”解决方案的人,我认为您会发现这很有用。

                              代码

                              代码可在 GitHub 上找到,其中包含一组相当不错的测试:

                              https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination

                              如果您有兴趣,我还写了一篇简短的文章,对模块的设计有更深入的了解:http://www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs/

                              【讨论】:

                              • 嗨@michael bromley,我正在尝试使用angularUtils。我已将 dirPangination.js 和 dirPagination.tpl.html 文件添加到我的项目中。但我开始收到类似“[$compile:tpload] Failed to load template:directives/pagination/dirPagination.tpl.html”的错误。我试图把这个 html 文件放在我项目的指令文件夹中。但我没有成功。我有以下疑问: 1. 将 dirPagination.tpl.html 放在项目中的哪个位置(因为我在 Angularjs 上使用 ruby​​ on rails)?
                              • 整洁,当我读到分页可以在页面中的任何位置时,你让我受益匪浅:) 目前正在使用它并且工作顺利。
                              • 这是最好的 Angular 分页指令。这可能是我见过的最简单的分页解决方案。我在 15 分钟内启动并为每个视图分页多个表,每个表都有自己的独立分页控件。每个 .jade 文件都有两行代码。我只能说哇。太棒了!
                              • 我可以保证这个指令的出色,我有一个复杂的 ng-repeat 并且它处理它没有问题。超级简单的设置。
                              • 您的“tracker()”方法可以节省我的时间。没有它,我会有一种可怕而罕见的行为。
                              【解决方案19】:

                              以前的消息基本上推荐了如何自己构建分页。如果您像我一样,并且更喜欢完成的指令,我刚刚找到了一个很棒的指令,叫做ngTable。它支持排序、过滤和分页。

                              这是一个非常干净的解决方案,在你看来,你所需要的一切:

                                 <table ng-table="tableParams" class="table">
                                      <tr ng-repeat="user in $data">
                                          <td data-title="'Name'" sortable="'name'">
                                              {{user.name}}
                                          </td>
                                          <td data-title="'Age'" sortable="'age'">
                                              {{user.age}}
                                          </td>
                                      </tr>
                                  </table>
                              

                              在控制器中:

                              $scope.tableParams = new ngTableParams({
                                  page: 1,            // show first page
                                  count: 10,          // count per page
                                  sorting: {
                                      name: 'asc'     // initial sorting
                                  }
                              }, {
                                  total: data.length, // length of data
                                  getData: function($defer, params) {
                                      // use build-in angular filter
                                      var orderedData = params.sorting() ?
                                                          $filter('orderBy')(data, params.orderBy()) :
                                                          data;
                              
                                      var start = (params.page() - 1) * params.count();
                                      var end = params.page() * params.count();
                              
                                      $defer.resolve(orderedData.slice( start, end));
                                  }
                              });
                              

                              GitHub 链接:https://github.com/esvit/ng-table/

                              【讨论】:

                                【解决方案20】:

                                我刚刚制作了一个 JSFiddle,使用 btford 代码在每列上显示分页 + 搜索 + 排序:http://jsfiddle.net/SAWsA/11/

                                【讨论】:

                                • 感谢您的提琴。它非常有用。但问题是:您将如何对整个结果集而不是当前页面上的内容进行排序?
                                • 请注意,排序仅适用于当前页面...它不会对整个数组进行排序。每次更改排序顺序时都必须重做分页
                                • @Spir:是的,搜索有效,但排序无效。如果在第 1 页反转排序,则仅重新排序此页,而不是显示第 9、20 和 co
                                • @AleckLandgraf 我尝试添加 $scope.search 但 ii 仍然没有显示正确的排序列表。请让我知道您还尝试或添加了什么
                                • @simmisimmi @Spir @scenario 在 javascript 的底部有一个错误:new_sorting_order 应该是 newSortingOrder。解决这个问题,添加@scope.search();,您会看到按预期排序,排序图标也会更新。 (在浏览器的调试控制台打开的情况下运行小提琴(在 chrome、F12、控制台选项卡中),这很明显)。
                                【解决方案21】:

                                我最近为 Built with Angular 网站实现了分页。您可以查看来源:https://github.com/angular/builtwith.angularjs.org

                                我会避免使用过滤器来分隔页面。您应该将项目分解为控制器内的页面。

                                【讨论】:

                                • 解决方案分布在多个文件中。您至少需要查看控制器和视图。我不明白这有什么理由反对:Use your downvotes whenever you encounter an egregiously sloppy, no-effort-expended post, or an answer that is clearly and perhaps dangerously incorrect.
                                • @btford 为什么要避免使用过滤器?
                                • 我投了赞成票以抵消之前的反对票,因为我觉得海报提供了一个可以用来回答原始问题的优质示例。
                                • @btford 使用过滤器进行分页仍然是个坏主意吗?这是一个通过看起来高效的过滤器对列表进行分页的 plunkr(至少在这个简单的示例中最多 10 000 000 行):embed.plnkr.co/iWxWlCEvd6Uh8erUOyaF
                                【解决方案22】:

                                jQuery Mobile 角度适配器有一个分页过滤器,您可以以此为基础。

                                这是一个使用它的演示小提琴(添加超过 5 个项目,它变成分页):http://jsfiddle.net/tigbro/Du2DY/

                                来源:https://github.com/tigbro/jquery-mobile-angular-adapter/blob/master/src/main/webapp/utils/paging.js

                                【讨论】:

                                  猜你喜欢
                                  相关资源
                                  最近更新 更多
                                  热门标签