Ho un set di dati di circa 1000 elementi in memoria e sto tentando di creare un cercapersone per questo set di dati, ma non sono sicuro su come farlo.
Sto usando una funzione di filtro personalizzata per filtrare i risultati, e questo funziona bene, ma in qualche modo ho bisogno di ottenere il numero di pagine.
Qualche indizio?
Controlla la direttiva di impaginazione dell’UI Bootstrap . Ho finito per usarlo piuttosto che ciò che è pubblicato qui in quanto ha abbastanza funzionalità per il mio uso corrente e ha una specifica di prova approfondita per accompagnarlo.
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); }); });
Ho fatto un plunker funzionante per riferimento.
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); }); });
Ho fatto un plunker funzionante per riferimento.
Di recente ho implementato il paging per il sito Built with Angular. Puoi controllare la fonte: https://github.com/angular/builtwith.angularjs.org
Eviterei di usare un filtro per separare le pagine. È necessario suddividere gli articoli in pagine all’interno del controller.
Ho dovuto implementare l’impaginazione diverse volte con Angular, ed era sempre un po ‘un dolore per qualcosa che sentivo potesse essere semplificato. Ho usato alcune delle idee presentate qui e altrove per creare un modulo di impaginazione che rende l’impaginazione semplice come:
- {{ item }}
// then somewhere else on the page ....
Questo è tutto. Ha le seguenti caratteristiche:
items
della raccolta ai collegamenti di impaginazione. ng-repeat
, quindi puoi usare qualsiasi espressione che possa essere validamente usata in una ng-repeat
, incluso il filtraggio, l’ordinamento, ecc. pagination-controls
non ha bisogno di sapere nulla sul contesto in cui viene chiamata la direttiva paginate
. Per coloro che sono alla ricerca di una soluzione “plug and play”, penso che lo troverai utile.
Il codice è disponibile qui su GitHub e include una serie di test piuttosto buona:
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
Se sei interessato, ho anche scritto un breve pezzo con un po ‘di più informazioni sul design del modulo: http://www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs/
Ho appena creato un JSFiddle che mostra l’impaginazione + cerca + ordina per ogni colonna usando il codice btford: http://jsfiddle.net/SAWsA/11/
Ho aggiornato il plunkr di Scotty.NET http://plnkr.co/edit/FUeWwDu0XzO51lyLAEIA?p=preview in modo che utilizzi versioni più recenti di angular, angular-ui e bootstrap.
controllore
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(); }; });
Componente dell'interfaccia utente Bootstrap
Questa è una pura soluzione javascript che ho avvolto come servizio angular per implementare la logica di impaginazione come nei risultati di ricerca di Google.
Dimostrazione di lavoro su CodePen su http://codepen.io/cornflourblue/pen/KVeaQL/
Dettagli e spiegazioni in questo post del blog
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 }; } }
Ho estratto i bit rilevanti qui. Questo è un cercapersone tabulare “senza fronzoli”, quindi l’ordinamento o il filtraggio non è incluso. Sentiti libero di cambiare / aggiungere se necessario:
//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 (ie our model) $scope.pages = new $window.Util.Pager($scope.ModelData); }; })(window.Controllers = window.Controllers || {});
Col1 « {{n + 1}} »
L’adattatore angular jQuery Mobile ha un filtro cercapersone da cui potresti partire.
Ecco un demo fiddle che lo usa (aggiungi più di 5 elementi e diventa paginato): http://jsfiddle.net/tigbro/Du2DY/
Ecco la fonte: https://github.com/tigbro/jquery-mobile-angular-adapter/blob/master/src/main/webapp/utils/paging.js
Io uso questa libreria di paginazione di terze parti e funziona bene. Può fare origini dati remote / locali ed è molto configurabile.
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
Sotto soluzione abbastanza semplice.
Ecco un esempio di jsfiddle
Per chiunque abbia difficoltà come me a creare un cercapersone per un tavolo, lo postò. Quindi, secondo te:
//And don't forget in your table:
Nei tuoi angularJ:
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 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); }; });
impaginazione ripetuta
- {{item}}
{{currentPage+1}}/{{numberOfPages()}}
Dal momento che Angular 1.4, il filtro limitTo
accetta anche un secondo argomento opzionale begin
Dai documenti :
{{limitTo_expression | limitTo: limit: begin}}
inizio (facoltativo) stringa | numero
Indice al quale iniziare la limitazione. Come indice negativo, inizia indica un offset dalla fine dell’input. Il valore predefinito è 0.
Quindi non è necessario creare una nuova direttiva , Questo argomento può essere usato per impostare l’offset dell’impaginazione
ng-repeat="item in vm.items| limitTo: vm.itemsPerPage: (vm.currentPage-1)*vm.itemsPerPage"
I messaggi precedenti raccomandavano fondamentalmente come build un paging da soli. Se sei come me, e preferisci una direttiva finita, ne ho trovato uno fantastico chiamato ngTable . Supporta l’ordinamento, il filtraggio e l’impaginazione.
È una soluzione molto pulita, tutto ciò che serve nella tua vista:
{{user.name}} {{user.age}}
E nel controller:
$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)); } });
Link a GitHub: https://github.com/esvit/ng-table/
C’è il mio esempio. Pulsante selezionato in mezzo alla lista Controller. config >>>
$scope.pagination = {total: null, pages: [], config: {count: 10, page: 1, size: 7}};
Logica per impaginazione:
/* 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); });
e la mia opinione su bootstap
È utile
Angular-Paging
è una scelta meravigliosa
Una direttiva per aiutare nel paging di set di dati di grandi dimensioni pur richiedendo il minimo indispensabile di informazioni di paging effettive. Siamo molto dipendenti dal server per “filtrare” i risultati in questo schema di paging. L’idea centrale è che vogliamo solo contenere la “pagina” triggers degli elementi, piuttosto che contenere l’intero elenco di elementi in memoria e paging sul lato client.
Vecchia domanda ma poiché penso che il mio approccio sia un po ‘diverso e meno complesso, lo condividerò e spero che qualcuno oltre a me lo trovi utile.
Quello che ho trovato per essere una soluzione facile e piccola alla paginazione è combinare una direttiva con un filtro che utilizza le stesse variabili di scope.
Per implementarlo aggiungi il filtro sull’array e aggiungi il directiv in questo modo
Name Price Quantity {{item.Name}} {{item.Price}} {{item.Quantity}}
p_Size e p_Step sono variabili dell’ambito che possono essere personalizzate nell’ambito, altrimenti il valore predefinito di p_Size è 5 e p_Step è 1.
Quando un passaggio è modificato nell’impaginazione, p_Step viene aggiornato e attiverà un nuovo filtro dal filtro cust_pagination. Il filtro cust_pagination taglia quindi l’array in base al valore p_Step come sotto e restituisce solo i record attivi selezionati nella sezione di paginazione
var startIndex = nStep * nPageSize; var endIndex = startIndex + nPageSize; var arr = items.slice(startIndex, endIndex); return arr;
DEMO Visualizza la soluzione completa in questo plunker
Vorrei poter commentare, ma dovrò lasciare questo qui:
La risposta di Scotty.NET e la ripetizione di user2176745 per le versioni successive sono entrambe ottime, ma entrambi mancano qualcosa su cui si interrompe la mia versione di AngularJS (v1.3.15):
non è definito in $ scope.makeTodos.
Come tale, la sostituzione con questa funzione lo risolve per versioni angolari più recenti.
$scope.makeTodos = function() { var i; $scope.todos = []; for (i=1;i<=1000;i++) { $scope.todos.push({ text:'todo '+i, done:false}); } };
Panoramica : utilizzo della paginazione
- ng-repeat - uib-pagination
Visualizza :
Dispature Service Host Value {{x.dispature}} {{x.service}} {{x.host}} {{x.value}} Page: {{app.currentPage}} / {{numPages}}Controller 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(); }]);
Puoi farlo facilmente usando la direttiva UI Bootstrap.
Questa risposta è una modifica della risposta data da @ Scotty.NET, ho cambiato il codice perché la direttiva
è deprecata ora.
Il seguente codice genera l’impaginazione:
Per renderlo funzionale, usa questo nel tuo controller:
$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();
Fare riferimento a questo per ulteriori opzioni di impaginazione: Direttiva di impaginazione dell’interfaccia utente Bootstrap
Vorrei aggiungere la mia soluzione che funziona con ngRepeat
e i filtri che si utilizzano con esso senza utilizzare un $watch
o un array affettato.
I risultati del filtro verranno impaginati!
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; }; }]);
Nell'HTML assicurati di applicare i filtri a ngRepeat
prima del filtro di impaginazione.
{{item}}