Phân trang trên danh sách bằng ng-repeat


130

Tôi đang cố gắng thêm các trang vào danh sách của mình. Tôi đã làm theo hướng dẫn của AngularJS, một bài về điện thoại thông minh và tôi đang cố gắng chỉ hiển thị một số đối tượng nhất định. Đây là tập tin html của tôi:

  <div class='container-fluid'>
    <div class='row-fluid'>
        <div class='span2'>
            Search: <input ng-model='searchBar'>
            Sort by: 
            <select ng-model='orderProp'>
                <option value='name'>Alphabetical</option>
                <option value='age'>Newest</option>
            </select>
            You selected the phones to be ordered by: {{orderProp}}
        </div>

        <div class='span10'>
          <select ng-model='limit'>
            <option value='5'>Show 5 per page</option>
            <option value='10'>Show 10 per page</option>
            <option value='15'>Show 15 per page</option>
            <option value='20'>Show 20 per page</option>
          </select>
          <ul class='phones'>
            <li class='thumbnail' ng-repeat='phone in phones | filter:searchBar | orderBy:orderProp | limitTo:limit'>
                <a href='#/phones/{{phone.id}}' class='thumb'><img ng-src='{{phone.imageUrl}}'></a>
                <a href='#/phones/{{phone.id}}'>{{phone.name}}</a>
                <p>{{phone.snippet}}</p>
            </li>
          </ul>
        </div>
    </div>
  </div>

Tôi đã thêm một thẻ chọn với một số giá trị để giới hạn số lượng mục sẽ được hiển thị. Điều tôi muốn bây giờ là thêm phân trang để hiển thị 5, 10, v.v.

Tôi có một bộ điều khiển hoạt động với điều này:

function PhoneListCtrl($scope, Phone){
    $scope.phones = Phone.query();
    $scope.orderProp = 'age';
    $scope.limit = 5;
}

Và tôi cũng có một mô-đun để lấy dữ liệu từ các tệp json.

angular.module('phonecatServices', ['ngResource']).
    factory('Phone', function($resource){
        return $resource('phones/:phoneId.json', {}, {
            query: {method: 'GET', params:{phoneId:'phones'}, isArray:true}
        });
    });

1
Khi bạn nói rằng bạn muốn triển khai trang tiếp theo và trang trước, bạn có muốn phân trang xảy ra hoàn toàn ở phía máy khách hoặc phía máy chủ. Nếu số lượng hồ sơ quá nhiều thì bạn nên chọn phân trang phía máy chủ. Trong bất kỳ kịch bản nào bạn cần để bắt đầu duy trì "start Index" - giới hạn sẽ chỉ cung cấp số lượng hồ sơ trên trang, ngoài điều này bạn cần một số cách duy trì trang hiện tại - điều này có thể được thực hiện bằng cách duy trì start Index.
Rutesh Makhi camera

Tôi không có nhiều hồ sơ. Những gì tôi muốn làm là sử dụng bộ điều khiển tôi đã có (PhoneListCtrl). Tôi không biết đó là phía máy chủ hay máy khách. Lấy làm tiếc!
Tomarto

1
@RuteshMakhi camera Tôi có một yêu cầu tương tự với số lượng hồ sơ cao, vui lòng giải thích lý do đằng sau việc sử dụng phân trang phía máy chủ cho số lượng hồ sơ cao
Dinesh PR

Câu trả lời:


215

Nếu bạn không có quá nhiều dữ liệu, bạn hoàn toàn có thể thực hiện phân trang bằng cách chỉ lưu trữ tất cả dữ liệu trong trình duyệt và lọc những gì hiển thị tại một thời điểm nhất định.

Đây là một ví dụ phân trang đơn giản: http://jsfiddle.net/2ZzZB/56/

Ví dụ đó nằm trong danh sách các câu đố trên wiki github angular.js, rất hữu ích: https://github.com/angular/angular.js/wiki/JsFiddle-Examples

EDIT: http://jsfiddle.net/2ZzZB/16/ đến http://jsfiddle.net/2ZzZB/56/ (sẽ không hiển thị "1 / 4.5" nếu có 45 kết quả)


1
Cảm ơn rât nhiều! Nó chính xác là những gì tôi đang tìm kiếm. Tôi đã thấy ví dụ đó sớm hơn nhưng nó không hoạt động. Bây giờ tôi nhận thấy có một lỗi cú pháp nhỏ. Một dấu ngoặc bị thiếu sau câu "for".
Tomarto

Tôi đã thêm dấu ngoặc và cập nhật nó trên wiki. Nhưng nó nên hoạt động mà không có chúng.
Andrew Joslin

1
Oh! đừng bận tâm. Tôi thêm một if (input?)điều kiện trước khi trở về input.slice(start), cảm ơn Andy!
zx1986

1
Giống như Bart, tôi cần chuyển thông tin phân trang vào một chức năng gọi để có được dữ liệu có thể phân trang - nó tương tự nhưng khác nhau và có thể giúp ích trong một số trường hợp. plnkr.co/edit/RcSso3verGtXwToilJ5a
Steve Black

3
Xin chào, bản demo này rất tiện cho dự án mà tôi tham gia. Tôi cần thêm tùy chọn để xem tất cả hoặc chuyển đổi phân trang cũng như hiển thị từng trang. Vì vậy, tôi đã mở rộng bản demo. cảm ơn rất nhiều. jsfiddle.net/juanmendez/m4dn2xrv
Juan Mendez

39

Tôi vừa tạo một JSFiddle hiển thị phân trang + tìm kiếm + thứ tự trên mỗi cột bằng cách sử dụng mã Buildstrap của Build with Twitter : http://jsfiddle.net/SAWsA/11/


2
Công việc tuyệt vời Tốt hơn là tiến thêm một bước và làm cho các tiêu đề cột trở nên động, tức là lấy tất cả các giá trị khóa duy nhất từ ​​mảng json và liên kết nó với một lần lặp lại thay vì mã hóa cứng các giá trị. Một cái gì đó giống như những gì tôi đã làm ở đây: jsfiddle.net/gavinfoley/t39ZP
GFoley83

có tất cả những gì mã trong bộ điều khiển chỉ làm cho nó ít tái sử dụng - telerik.com/help/silverlight/... vẻ góc là mất tích: QueryableDomainServiceCollectionView, VirtualQueryableCollectionView, HierarchicalDataCollectionView
Leblanc Meneses

1
Đây là một giải pháp thực sự tuyệt vời, dễ thích nghi. Đã sử dụng nó trên một kịch bản phức tạp trong đó số lượng hai phần tử liên kết đã lên tới hàng nghìn và nó thực sự không phải là một tùy chọn để cấu trúc lại toàn bộ mã. Bạn nên cập nhật câu trả lời với một số mã giải thích các nguyên tắc cơ bản. Và có lẽ nâng cấp các phiên bản AngularJS và Bootstrap trong fiddle :)
davidkonrad

15

Tôi đã xây dựng một mô-đun giúp phân trang trong bộ nhớ cực kỳ đơn giản.

Nó cho phép bạn phân trang bằng cách thay thế ng-repeatbằngdir-paginate , chỉ định các mục trên mỗi trang dưới dạng bộ lọc theo đường ống, sau đó thả các điều khiển bất cứ nơi nào bạn muốn dưới dạng một lệnh,<dir-pagination-controls>

Lấy ví dụ ban đầu mà Tomarto hỏi, nó sẽ giống như thế này:

<ul class='phones'>
    <li class='thumbnail' dir-paginate='phone in phones | filter:searchBar | orderBy:orderProp | limitTo:limit | itemsPerPage: limit'>
            <a href='#/phones/{{phone.id}}' class='thumb'><img ng-src='{{phone.imageUrl}}'></a>
            <a href='#/phones/{{phone.id}}'>{{phone.name}}</a>
            <p>{{phone.snippet}}</p>
    </li>
</ul>

<dir-pagination-controls></dir-pagination-controls>

Không cần bất kỳ mã phân trang đặc biệt nào trong bộ điều khiển của bạn. Tất cả được xử lý nội bộ bởi các mô-đun.

Bản giới thiệu: http://plnkr.co/edit/Wtkv71LIqUR4OhzhgpqL?p=preview

Nguồn: dirPagination của GitHub


JFI: Thay vì tách riêng dirPagination.tpl.html, chúng tôi cũng có thể bao gồm mã phân trang bên trong <dir-pagination-controls> <ul class = "pagination" ng-if = "1 <Pages.length ||! AutoHide">. .. </ ul> </ dir-pagination-controls>
npcoder

5

Tôi biết chủ đề này đã cũ nhưng tôi đang trả lời nó để giữ cho mọi thứ được cập nhật một chút.

Với góc 1,4 trở lên, bạn có thể trực tiếp sử dụng limitTo lọc mà ngoài việc chấp nhận các limittham số cũng chấp nhận mộtbegin tham số.

Sử dụng: {{ limitTo_expression | limitTo : limit : begin}}

Vì vậy, bây giờ bạn có thể không cần sử dụng bất kỳ thư viện bên thứ ba nào để đạt được thứ gì đó như phân trang. Tôi đã tạo ra một fiddle để minh họa tương tự.


Fiddle bạn liên kết đến không thực sự sử dụng tham số bắt đầu.
Người đàn ông cãi lộn

3

Kiểm tra chỉ thị này: https://github.com/samu/angular-table

Nó tự động sắp xếp và phân trang rất nhiều và cho bạn đủ tự do để tùy chỉnh bảng / danh sách của bạn theo cách bạn muốn.


Thoạt nhìn, nó trông giống hệt những gì tôi cần, nhưng dường như tôi không thể làm cho nó hoạt động được với tài nguyên $. Có vẻ như nó luôn nghĩ rằng danh sách của tôi trống ở đây: github.com/ssmm/angular-table/blob/master/coffee/ tựa ... vẫn chưa thể hiểu tại sao. : /
Mike Desjardins

Làm cách nào để hiển thị Sno trong cột đầu tiên vì tôi không thể sử dụng $indexvà mảng của tôi không chứa các giá trị gia tăng
Dwigh

tôi đã làm điều này: <td at-sortable at-attribute="index">{{sortedAndPaginatedList.indexOf(item) + 1}}</td>nhưng tôi không biết liệu đó có phải là cách đúng hay không
Dwigh

2

Đây là mã demo trong đó có phân trang + Lọc với AngularJS:

https://codepen.io/lamjaguar/pen/yOrVym

JS:

var app=angular.module('myApp', []);

// alternate - https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
// alternate - http://fdietz.github.io/recipes-with-angular-js/common-user-interface-patterns/paginating-through-client-side-data.html

app.controller('MyCtrl', ['$scope', '$filter', function ($scope, $filter) {
    $scope.currentPage = 0;
    $scope.pageSize = 10;
    $scope.data = [];
    $scope.q = '';

    $scope.getData = function () {
      // needed for the pagination calc
      // https://docs.angularjs.org/api/ng/filter/filter
      return $filter('filter')($scope.data, $scope.q)
     /* 
       // manual filter
       // if u used this, remove the filter from html, remove above line and replace data with getData()

        var arr = [];
        if($scope.q == '') {
            arr = $scope.data;
        } else {
            for(var ea in $scope.data) {
                if($scope.data[ea].indexOf($scope.q) > -1) {
                    arr.push( $scope.data[ea] );
                }
            }
        }
        return arr;
       */
    }

    $scope.numberOfPages=function(){
        return Math.ceil($scope.getData().length/$scope.pageSize);                
    }

    for (var i=0; i<65; i++) {
        $scope.data.push("Item "+i);
    }
  // A watch to bring us back to the 
  // first pagination after each 
  // filtering
$scope.$watch('q', function(newValue,oldValue){             if(oldValue!=newValue){
      $scope.currentPage = 0;
  }
},true);
}]);

//We already have a limitTo filter built-in to angular,
//let's make a startFrom filter
app.filter('startFrom', function() {
    return function(input, start) {
        start = +start; //parse to int
        return input.slice(start);
    }
});

HTML:

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.