<idf-pagination data="paginate"></idf-pagination>
где paginate объект вида
$scope.paginate = {
per_page: 10,
total: null,
page: 1
};
при изменении страницы меняется $scope.paginate.page, на него надо повесить листнер и производить действия по изменению, например:
$scope.$watch("paginate", function(data, oldData){
if(data.page == oldData.page) return;
reloadData();
}, true);
Постраничка не показывается, если нет total и если доступна только 1 страница.
Листинг модуля idf-pagination.js
angular.module('idfPagination', []).directive('idfPagination', [function() {
return {
restrict: 'E',
scope: {
data: '=',
change: '='
},
template: '<div class="row" ng-if="data.total && data.total > data.per_page">' +
' <div class="col-sm-5 animated-panel">' +
' <div class="dataTables_info">' +
' Showing {{(data.page - 1) * data.per_page + 1}} to {{max()}} of {{data.total}} entries' +
' </div>' +
' </div>' +
' <div class="col-sm-7 animated-panel" ng-if="data.total > data.per_page">' +
' <div class="paging_simple_numbers pull-right">' +
' <ul class="pagination no-margins">' +
' <li class="paginate_button previous" ng-class="{disabled: data.page <= 1}">' +
' <a class="pointer" ng-click="setPage(data.page - 1)">Previous</a>' +
' </li>' +
' <li class="paginate_button" ng-repeat="num in pagesArray track by $index" ng-class="{active: $index + 1 == data.page}">' +
' <a class="pointer" ng-click="setPage($index + 1)">{{$index + 1}}</a>' +
' </li>' +
' <li class="paginate_button next" ng-class="{disabled: data.page >= numPages}">' +
' <a class="pointer" ng-click="setPage(data.page + 1)">Next</a>' +
' </li>' +
' </ul>' +
' </div>' +
' </div>' +
'</div>',
controller: function($scope){
$scope.$watch("data", function(data, oldData){
if(data.total == oldData.total) return;
$scope.numPages = Math.ceil($scope.data.total / $scope.data.per_page);
$scope.pagesArray = [];
for(var num = 0; num < $scope.numPages; num++){
$scope.pagesArray.push(num);
}
}, true);
$scope.max = function(){
var max = $scope.data.page * $scope.data.per_page;
return max < $scope.data.total ? max : $scope.data.total;
};
$scope.setPage = function(page){
if(page < 1 || page > $scope.numPages || page == $scope.data.page) return;
$scope.data.page = page;
};
}
};
}]);
Если у Вас есть замечания/предложения как сделать лучше с удовольствием выслушаем. Если есть вопросы тоже задавайте, ответим.
Комментарии (21)
awMinor
05.05.2016 11:55+2Мне кажется, что лучше было бы не вешать лисенер на объект грубо говоря настроек пагинации, а позволить передать в дериктиву функцию которая будет дергатся при изменении страницы и отдать туда её номер.
А ещё заметил, что если страница меньше 1 или больше максимума, то вы делаете return. Не лучше ли в таких случаях переводить юзера на максимальное или минимальное значение? Ведь это исключительные случаи, врятле кто-то руками будет передавать не валидное значение.
impwx
05.05.2016 11:58+2Зачем вы используете
$index
? У вас каждый элемент массива равен$index-1
, дубликатов не будет — можно было бы взять непосредственноnum
и не использоватьtrack by
.
Вscope
объявлено свойствоchange
, которое нигде не используется.
Стилизовать и локализовать нельзя.
Если страниц вдруг будет действительно много, покажется весь список, хотя обычно промежуточные значения между текущей страницей и краями скрывают, вот так:
У вас получился компонент для решения вашей конкретной задачи, но это не библиотека для широкого использования.
bromzh
05.05.2016 12:00+1Если у Вас есть замечания/предложения как сделать лучше с удовольствием выслушаем.
1) Бегом смотреть styleguide.
2) Зачем использовать $watch и $scope там, где не надо?
3) Со стороны UI посмотрите на эту реализацию
4) Никакой гибкости. Например, Spring умеет отдавать коллекции в pagable-виде. Данные о странице передаются в гет-параметрах. Хочется автоматизировать этот процесс.
5) Почему не angular 2?
Akuma
Вопрос только один. Зачем вы выложили это здесь?
Туториал по первому Ангуляру содержит больше информации и примеров кода, чем эта статья.
К тому же, подобную директиву сможет создать человек, который знает Ангуляр… ну минут 15.
Про стили вы кстати забыли. Видно, что используется какой-то CSS фрейморк, подозреваю, что Foundation, но могу ошибаться.
mlnewton
Можно ссылку на туториал о котором вы говорите? Отвечая на ваш вопрос, этот модуль может сэкономить многим время и может быть деньги. Не все такие крутые специалисты как Вы чтобы написать такое за 15 минут.
Akuma
Эм. Я имел ввиду не «написать за 15 минут», а человек, который знает Ангуляр 15 минут, может подобное написать достаточно быстро и без проблем.
Например, официальный туториал: https://docs.angularjs.org/tutorial
Если чисто ради обучения, вот пара моментов:
1. Не обрабатывается ситуация, когда количество страниц уменьшилось, а выбранной осталась страница которая уже не существует.
2. Сделайте так: controller: ['$scope', function($scope){
3. Если страниц будет много — будет огромный список ссылок.
mlnewton
Спасибо, учтем
Odrin
Судя по «row» и «col-sm-x», используется bootstrap, что лишает данный модуль всякого смысла, т.к. существует angular ui bootstrap, в котором есть uib-pager.
m0sk1t
Да чем ещё заняться гендиректору, как не выкладывать статьи на хабр? Скучно жеж на работе =)
mlnewton
Вы не невеста случаем? А то моему другу нужна :)
m0sk1t
Эммм, где вы видели невесту с именем Артём? А вы ещё сводничеством от скуки занимаетесь? =) Прошу не принимать близко к сердцу мои подколы… Просто у ваших предыдущих статей был совершенно другой уровень, а этот топик я воспринимаю как неудачную попытку пятничного поста.
mlnewton
простите не заметил имя)))) Только на город обратил внимание) Много чем занимаюсь, подробнее в личку спрашиваете расскажу, если интересно, а тут по теме пожалуйста )
m0sk1t
По теме: вы презентуете модуль, который недоработан, содержит ошибки, не особо гибкий и т.д. (в комментариях уже расписали). Нет ссылки на github, нет инструкций для подключения (согласен, тривиальщина, но надо иметь в виду что есть начинающие разработчики). Короче говоря — презентация не удалась.
mlnewton
Спасибо за полезную информацию, учтём)