ng-repeatを使用したリストのページネーション


130

リストにページを追加しようとしています。スマートフォンに関するものであるAngularJSチュートリアルに従い、特定の数のオブジェクトのみを表示しようとしています。これが私のhtmlファイルです:

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

表示される項目の数を制限するために、いくつかの値を持つ選択タグを追加しました。私が今欲しいのは、次の5、10などを表示するためにページ付けを追加することです。

私はこれで動作するコントローラーを持っています:

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

また、jsonファイルからデータを取得するためのモジュールもあります。

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

1
次のページと前のページを実装したい場合、ページネーションを純粋にクライアント側で行うか、サーバー側で行うかを指定します。レコードの数が多すぎる場合は、サーバー側のページ分割を選択する必要があります。どのような状況でも、「startIndex」の維持を開始する必要があります-制限はページ上のレコード数のみを提供します。これとは別に、現在のページを維持する方法が必要です-これは、startIndexを維持することで実行できます。
Rutesh Makhijani 2012

レコード数が少ない。私がやりたかったのは、すでに持っているコントローラー(PhoneListCtrl)を使用することです。サーバー側かクライアント側かわかりません。ごめんなさい!
トマルト2012

1
@RuteshMakhijani多数のレコードで同様の要件があります。多数のレコードにサーバー側のページネーションを使用する理由を説明してください
Dinesh PR

回答:


215

データが多すぎない場合は、ブラウザにすべてのデータを保存し、特定の時間に表示されるものをフィルタリングするだけで、確実にページ分割を行うことができます。

これは簡単なページネーションの例です: http //jsfiddle.net/2ZzZB/56/

その例は、angular.js github wikiのフィドルのリストにありました。役立つはずです。https//github.com/angular/angular.js/wiki/JsFiddle-Examples

編集:http : //jsfiddle.net/2ZzZB/16/ から http://jsfiddle.net/2ZzZB/56/(45の結果がある場合、「1 / 4.5」は表示されません)


1
どうもありがとうございました!それはまさに私が探していたものです。先ほどその例を見ましたが、うまくいきませんでした。今、私は少し構文エラーがあることに気づきました。「for」文の後にブラケットがありません。
Tomarto

かっこを追加して、wikiで更新しました。しかし、それらがなくても機能するはずです。
アンドリュージョスリン

1
ああ!気にしないで。if (input?)戻る前に条件を追加しますinput.slice(start)。アンディに感謝します。
zx1986

1
Bartのように、ページング可能なデータを取得するためにページング情報を呼び出し関数に渡す必要がありました。これは似ていますが異なり、場合によっては役立つ場合があります。plnkr.co/edit/RcSso3verGtXwToilJ5a
スティーブブラック

3
こんにちは、このデモは私が関わったプロジェクトにとても便利でした。すべてを表示するオプションを追加するか、ページ付けを切り替えて各ページを表示する必要がありました。だから私はデモを拡張しました。どうもありがとう。jsfiddle.net/juanmendez/m4dn2xrv
ファンメンデス

39

Build with Twitter Bootstrap code:http : //jsfiddle.net/SAWsA/11/を使用して、各ページでページネーション+検索+​​順序を示すJSFiddleを作成しました


2
素晴らしい仕事。さらに一歩踏み込んで、列見出しを動的にすることをお勧めします。つまり、アイテムのjson配列からすべての一意のキー値を取得し、値をハードコーディングする代わりにng-repeatにバインドします。ここで私がしたことのようなもの:jsfiddle.net/gavinfoley/t39ZP
GFoley83

コントローラにそのすべてのコードがあると、再利用性が低下し ます-telerik.com/help/silverlight/…角度が欠けているようです:QueryableDomainServiceCollectionView、VirtualQueryableCollectionView、HierarchicalDataCollectionView
Leblanc Meneses

1
これは非常に優れたソリューションであり、簡単に適応できます。2つのバインドされた要素の数が数千に達し、コード全体をリファクタリングするオプションではなかった複雑なシナリオで使用しました。基本的な原則を説明するコードで回答を更新する必要があります。そして、おそらくフィドルでAngularJSとBootstrapのバージョンをアップグレードしてください:)
davidkonrad 2017年

15

私は、メモリ内のページ分割を信じられないほど簡単にするモジュールを作成しました。

それはあなたが単に置き換えることにより、ページ付けすることを可能にするng-repeatdir-paginateページごとの項目をパイプフィルターとして指定し、単一のディレクティブの形式でコントロールを好きな場所にドロップ。<dir-pagination-controls>

Tomartoによって要求された元の例を取り上げると、次のようになります。

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

コントローラに特別なページネーションコードは必要ありません。すべてモジュール内部で処理されます。

デモ: http //plnkr.co/edit/Wtkv71LIqUR4OhzhgpqL?p=preview

ソース:GitHubのdirPagination


JFI:分離されたdirPagination.tpl.htmlの代わりに、<dir-pagination-controls> <ul class = "pagination" ng-if = "1 <pages.length ||!autoHide">内にページネーションコードを含めることもできます。 .. </ ul> </ dir-pagination-controls>
npcoder

5

私はこのスレッドが古いことを知っていますが、少し更新するためにそれに答えています。

Angular 1.4 以降では、limitパラメーターを受け入れるだけでなくパラメーターも受け入れるlimitToフィルターを直接使用できbeginます。

使用法: {{ limitTo_expression | limitTo : limit : begin}}

したがって、ページネーションのようなものを実現するために、サードパーティのライブラリを使用する必要がない場合があります。同じことを説明するためにフィドルを作成しました。


リンクしたフィドルは、実際にはbeginパラメータを使用していません。
ブラウニーマン'20

3

このディレクティブをチェックしてください: https //github.com/samu/angular-table

並べ替えとページ付けを大幅に自動化し、自由にテーブル/リストを自由にカスタマイズできます。


一見すると、これは私が必要としているもののように見えましたが、$ resourceで機能させることができません。ここでは常に私のリストが空であると考え られているようです:github.com/ssmm/angular-table/blob/master/coffee/… ...まだ理由がわかりません。:/
マイクデジャルダン2013

使用できず$index、配列に増分値が含まれていないため、最初の列にSnoを表示する方法
Dwigh

私はこれをしました:<td at-sortable at-attribute="index">{{sortedAndPaginatedList.indexOf(item) + 1}}</td>しかし、それが正しい方法であるかどうかはわかりません
ドワイグ

2

以下は、AgularJSによる改ページ+フィルタリングがあるデモコードです。

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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.