Пагинація у списку за допомогою ng-повтору


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.
Рутеш Махіяні

У мене немає великої кількості записів. Що я хотів зробити - це використовувати контролер, який у мене вже є (PhoneListCtrl). Я не знаю, чи це сервер, чи клієнт. Вибачте!
Томарто

1
@RuteshMakhijani У мене є аналогічна вимога з великою кількістю записів, поясніть, будь ласка, причину використання пагинації на стороні сервера для великої кількості записів
Dinesh PR,

Відповіді:


215

Якщо у вас не надто багато даних, ви можете неодмінно зробити пагинацію, просто зберігаючи всі дані у браузері та фільтруючи те, що видно в певний час.

Ось простий приклад створення сторінки: http://jsfiddle.net/2ZzZB/56/

Цей приклад був у списку загадок на wiki.gith.js github, який має бути корисним: https://github.com/angular/angular.js/wiki/JsFiddle-Examples

EDIT: http://jsfiddle.net/2ZzZB/16/ до http://jsfiddle.net/2ZzZB/56/ (не буде показано "1 / 4,5", якщо є 45 результатів)


1
Велике спасибі! Це саме те, що я шукав. Я бачив цей приклад раніше, але він не працював. Тепер я помітив, що є невелика синтаксична помилка. Думка після речення "за" відсутня.
Томарто

Я додав дужки та оновив її на вікі. Але це мало б працювати без них.
Ендрю Джослін

1
ой! не звертай уваги. Я додаю if (input?)умову перед поверненням input.slice(start), дякую Енді!
zx1986

1
Як і Барту, мені потрібно було передати інформацію про підключення до функції виклику, щоб отримати дані, що відкриваються - вона схожа, але відрізняється і може допомогти в деяких випадках. plnkr.co/edit/RcSso3verGtXwToilJ5a
Стів Блек

3
Привіт, ця демонстрація стала такою зручною для проекту, в який я взяв участь. Мені потрібно було додати опцію для перегляду всіх або переключення сторінок, а також показ кожної сторінки. Тому я продовжив демонстрацію. дуже дякую. jsfiddle.net/juanmendez/m4dn2xrv
Хуан Мендес

39

Щойно я створив JSFiddle, який показує пагінацію + пошук + порядок у кожному стовпчику, використовуючи Build with Twitter Bootstrap code: http://jsfiddle.net/SAWsA/11/


2
Дивовижна робота. Будь ласка, зробіть ще один крок і зробіть заголовки стовпців динамічними, тобто отримайте всі унікальні ключові значення з масиву елементів json і прив’яжіть їх до ng-повтору замість жорсткого кодування значень. Щось схоже на те, що я тут робив: jsfiddle.net/gavinfoley/t39ZP
GFoley83

маючи весь цей код у контролері, він просто робить його менш використаним - telerik.com/help/silverlight/… Здається, кутовий відсутній: QueryableDomainServiceCollectionView, VirtualQueryableCollectionView, HierarchicalDataCollectionView
Leblanc Meneses

1
Це дійсно чудове рішення, легко адаптуватися. Використовували його за складним сценарієм, коли кількість двох прив’язаних елементів досягла тисяч, і це дійсно не було можливістю рефакторингу всього коду. Ви повинні оновити відповідь деяким кодом, що пояснює основні принципи. І, можливо, оновити версії AngularJS та Bootstrap у скрипці :)
davidkonrad

15

Я створив модуль, який робить розбиття в пам'яті неймовірно простим.

Це дозволяє посторінковою шляхом простої заміни ng-repeatз dir-paginateзазначенням елементів на сторінці , як централізованого фільтр, а потім опускаючи управління , де ви , як у вигляді однієї директиви,<dir-pagination-controls>

Якщо взяти оригінальний приклад, запитаний Томарто, це виглядатиме так:

<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

Джерело: dirPagination GitHub


JFI: Замість відокремленого dirPagination.tpl.html ми можемо також включити код пагинації всередині <dir-pagination-controls> <ul class = "pagination" ng-if = "1 <pages.length ||! AutoHide">. .. </ul> </dir-pagination-controls>
npcoder

5

Я знаю, що цей потік вже старий, але я відповідаю на нього, щоб все було трохи оновленим.

З кутовим 1.4 і вище ви можете безпосередньо використовувати limitTo фільтр, який крім прийняття limitпараметра також приймає beginпараметр.

Використання: {{ limitTo_expression | limitTo : limit : begin}}

Тож тепер вам може не знадобитися використовувати будь-яку сторонній бібліотеки, щоб досягти чогось типу пагинації. Я створив загадку, щоб проілюструвати те саме.


Загадка, з якою ви пов’язані, насправді не використовує параметр start.
The Brawny Man

3

Ознайомтеся з цією директивою: https://github.com/samu/angular-table

Це багато автоматизує сортування та пагинацію та дає вам достатньо свободи для налаштування таблиці / списку, скільки завгодно.


На перший погляд це виглядало як саме те, що мені потрібно, але я не можу зробити так, щоб він працював з ресурсом. Схоже, завжди здається, що мій список тут порожній: github.com/ssmm/angular-table/blob/master/coffee/… ... досі не змогли з’ясувати, чому ще. : /
Майк Дежардінс

як я показую Sno в першому стовпці, оскільки я не можу використовувати, $indexі мій масив не містить поступових значень
Dwigh

Я зробив це: <td at-sortable at-attribute="index">{{sortedAndPaginatedList.indexOf(item) + 1}}</td>але я не знаю, чи це правильний шлях
Двіг

2

Ось демонстраційний код, де є пагінація + фільтрування за допомогою 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.