Ng-tekrar kullanarak bir liste üzerinde sayfalama


130

Listeme sayfalar eklemeye çalışıyorum. Akıllı telefonlarla ilgili olan AngularJS eğitimini takip ettim ve yalnızca belirli sayıda nesneyi görüntülemeye çalışıyorum. İşte benim html dosyam:

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

Görüntülenecek öğe sayısını sınırlandırmak için bazı değerlere sahip bir seçme etiketi ekledim. Şimdi istediğim, sonraki 5, 10, vb.Görüntülemek için sayfalandırma eklemek.

Bununla çalışan bir denetleyicim var:

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

Ayrıca json dosyalarından verileri almak için bir modülüm var.

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

1
Bir sonraki sayfayı ve önceki sayfayı uygulamak istediğinizi söylediğinizde, sayfalandırmanın sadece istemci tarafında mı yoksa sunucu tarafında mı olmasını istiyorsunuz? Kayıt sayısı çok yüksekse, sunucu tarafında sayfalandırmayı tercih etmelisiniz. Herhangi bir senaryoda, "startIndex" i korumaya başlamanız gerekir - limit yalnızca sayfadaki kayıt sayısını sağlar, bunun dışında geçerli sayfanın nasıl korunacağına ihtiyacınız vardır - bu, startIndex'i koruyarak yapılabilir.
Rutesh Makhijani

Yüksek sayıda kaydım yok. Yapmak istediğim, zaten sahip olduğum denetleyiciyi kullanmak (PhoneListCtrl). Sunucu tarafı mı yoksa istemci tarafı mı bilmiyorum. Afedersiniz!
Tomarto

1
@RuteshMakhijani Çok sayıda kayıtla benzer bir gereksinimim var, lütfen yüksek sayıda kayıt için sunucu tarafı sayfalandırmanın kullanılmasının arkasındaki nedeni açıklayın
Dinesh PR

Yanıtlar:


215

Çok fazla veriniz yoksa, yalnızca tüm verileri tarayıcıda depolayarak ve belirli bir zamanda görünenleri filtreleyerek kesinlikle sayfalandırma yapabilirsiniz.

İşte basit bir sayfalama örneği: http://jsfiddle.net/2ZzZB/56/

Bu örnek, angular.js github wiki'deki keman listesindeydi ve yardımcı olması gerekir: https://github.com/angular/angular.js/wiki/JsFiddle-Examples

DÜZENLE: http://jsfiddle.net/2ZzZB/16/ - http://jsfiddle.net/2ZzZB/56/ (45 sonuç varsa "1 / 4.5" gösterilmez)


1
Çok teşekkür ederim! Tam olarak aradığım şey buydu. Bu örneği daha önce görmüştüm ama işe yaramadı. Şimdi küçük bir sözdizimi hatası olduğunu fark ettim. "For" cümlesinden sonra bir parantez eksik.
Tomarto

Parantezleri ekledim ve wiki'de güncelledim. Ama onlarsız çalışmalıydı.
Andrew Joslin

1
ah! boşver. if (input?)Dönmeden önce bir koşul ekliyorum input.slice(start), teşekkürler Andy!
zx1986

1
Bart gibi, sayfalandırılabilir verileri elde etmek için çağrı bilgisini bir arama işlevine aktarmam gerekiyordu - benzer ama farklı ve bazı durumlarda yardımcı olabilir. plnkr.co/edit/RcSso3verGtXwToilJ5a
Steve Black

3
Merhaba, bu demo dahil olduğum bir proje için çok kullanışlı oldu. Tümünü görüntüleme veya sayfalamayı değiştirmenin yanı sıra her sayfayı gösterme seçeneği eklemem gerekiyordu. Ben de demoyu uzattım. çok teşekkürler. jsfiddle.net/juanmendez/m4dn2xrv
Juan Mendez

39

Build with Twitter Bootstrap kodunu kullanarak her sütunda sayfalandırma + arama + sıralama gösteren bir JSFiddle yaptım : http://jsfiddle.net/SAWsA/11/


2
Harika iş. Bir adım daha ileri gitmek ve sütun başlıklarını dinamik yapmak, yani öğeler json dizisinden tüm benzersiz anahtar değerleri almak ve değerleri sabit kodlamak yerine bunu bir ng-yinelemeye bağlamak iyi olur. Burada yaptığım gibi bir şey: jsfiddle.net/gavinfoley/t39ZP
GFoley83

denetleyicide tüm bu koda sahip olmak onu daha az yeniden kullanılabilir hale getiriyor - telerik.com/help/silverlight/… Açısal eksik görünüyor: QueryableDomainServiceCollectionView, VirtualQueryableCollectionView, HierarchicalDataCollectionView
Leblanc Meneses

1
Bu gerçekten harika bir çözüm, uyarlaması kolay. Bunu, iki bağlı öğenin miktarının binlere ulaştığı karmaşık bir senaryoda kullandık ve tüm kodu yeniden düzenleme seçeneği değildi. Cevabı, temel ilkeleri açıklayan bazı kodlarla güncellemelisiniz. Ve belki de AngularJS ve Bootstrap sürümlerini keman içinde yükseltebilirsiniz :)
davidkonrad

15

Bellek içi sayfalamayı inanılmaz derecede basit hale getiren bir modül oluşturdum.

Bu sadece değiştirerek sayfalandırmak yapmanızı sağlar ng-repeatile dir-paginate, borulu filtre olarak sayfa başına öğeleri belirterek, ardından her yerde sizi tek bir direktif biçiminde gibi denetimleri bırakarak<dir-pagination-controls>

Tomarto'nun sorduğu orijinal örneği ele alırsak, şöyle görünecektir:

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

Denetleyicinizde herhangi bir özel sayfalama koduna gerek yoktur. Hepsi modül tarafından dahili olarak ele alınır.

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

Kaynak: GitHub'ın dirPagination


JFI: Ayrılmış dirPagination.tpl.html yerine, <dir-pagination-controls> <ul class = "pagination" ng-if = "1 <pages.length ||! AutoHide"> içine sayfalandırma kodunu da ekleyebiliriz. .. </ul> </dir-pagination-controls>
npcoder

5

Bu iş parçacığının artık eski olduğunu biliyorum, ancak işleri biraz güncel tutmak için yanıtlıyorum.

Angular 1.4 ve üstü ile , parametreyi kabul etmenin yanı sıra bir parametreyi de kabul eden limitTo filtresini doğrudan kullanabilirsiniz .limitbegin

Kullanımı: {{ limitTo_expression | limitTo : limit : begin}}

Yani artık sayfalandırma gibi bir şey elde etmek için herhangi bir üçüncü taraf kitaplığı kullanmanız gerekmeyebilir. Aynısını göstermek için bir keman yarattım .


Bağlandığınız keman aslında başlangıç ​​parametresini kullanmıyor.
Brawny Man

3

Bu yönergeye göz atın: https://github.com/samu/angular-table

Sıralama ve sayfalandırmayı büyük ölçüde otomatikleştirir ve tablonuzu / listenizi istediğiniz gibi özelleştirmeniz için size yeterli özgürlük sağlar.


İlk bakışta bu tam olarak ihtiyacım olan şey gibi görünüyordu, ancak onu $ resource ile çalıştırmayı başaramıyorum. Görünüşe göre burada her zaman listemin boş olduğunu düşünüyor: github.com/ssmm/angular-table/blob/master/coffee/… ... nedenini henüz çözemedim. : /
Mike Desjardins


bunu yaptım: <td at-sortable at-attribute="index">{{sortedAndPaginatedList.indexOf(item) + 1}}</td>ama doğru yol mu bilmiyorum
Dwigh

2

AngularJS ile sayfalandırma + Filtreleme olan bir demo kodu:

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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.