Использовать так:

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


  1. Akuma
    05.05.2016 11:51
    +7

    Вопрос только один. Зачем вы выложили это здесь?

    Туториал по первому Ангуляру содержит больше информации и примеров кода, чем эта статья.
    К тому же, подобную директиву сможет создать человек, который знает Ангуляр… ну минут 15.

    Про стили вы кстати забыли. Видно, что используется какой-то CSS фрейморк, подозреваю, что Foundation, но могу ошибаться.


    1. mlnewton
      05.05.2016 11:57
      -5

      Можно ссылку на туториал о котором вы говорите? Отвечая на ваш вопрос, этот модуль может сэкономить многим время и может быть деньги. Не все такие крутые специалисты как Вы чтобы написать такое за 15 минут.


      1. Akuma
        05.05.2016 12:04
        +2

        Эм. Я имел ввиду не «написать за 15 минут», а человек, который знает Ангуляр 15 минут, может подобное написать достаточно быстро и без проблем.

        Например, официальный туториал: https://docs.angularjs.org/tutorial

        Если чисто ради обучения, вот пара моментов:

        1. Не обрабатывается ситуация, когда количество страниц уменьшилось, а выбранной осталась страница которая уже не существует.
        2. Сделайте так: controller: ['$scope', function($scope){
        3. Если страниц будет много — будет огромный список ссылок.


        1. mlnewton
          05.05.2016 12:12
          +2

          Спасибо, учтем


    1. Odrin
      05.05.2016 17:08

      Судя по «row» и «col-sm-x», используется bootstrap, что лишает данный модуль всякого смысла, т.к. существует angular ui bootstrap, в котором есть uib-pager.


    1. m0sk1t
      06.05.2016 15:02

      Да чем ещё заняться гендиректору, как не выкладывать статьи на хабр? Скучно жеж на работе =)


      1. mlnewton
        06.05.2016 15:37
        -2

        Вы не невеста случаем? А то моему другу нужна :)


        1. m0sk1t
          06.05.2016 16:12

          Эммм, где вы видели невесту с именем Артём? А вы ещё сводничеством от скуки занимаетесь? =) Прошу не принимать близко к сердцу мои подколы… Просто у ваших предыдущих статей был совершенно другой уровень, а этот топик я воспринимаю как неудачную попытку пятничного поста.


          1. mlnewton
            06.05.2016 16:13

            простите не заметил имя)))) Только на город обратил внимание) Много чем занимаюсь, подробнее в личку спрашиваете расскажу, если интересно, а тут по теме пожалуйста )


            1. m0sk1t
              06.05.2016 16:21

              По теме: вы презентуете модуль, который недоработан, содержит ошибки, не особо гибкий и т.д. (в комментариях уже расписали). Нет ссылки на github, нет инструкций для подключения (согласен, тривиальщина, но надо иметь в виду что есть начинающие разработчики). Короче говоря — презентация не удалась.


              1. mlnewton
                06.05.2016 16:28

                Спасибо за полезную информацию, учтём)


  1. awMinor
    05.05.2016 11:55
    +2

    Мне кажется, что лучше было бы не вешать лисенер на объект грубо говоря настроек пагинации, а позволить передать в дериктиву функцию которая будет дергатся при изменении страницы и отдать туда её номер.

    А ещё заметил, что если страница меньше 1 или больше максимума, то вы делаете return. Не лучше ли в таких случаях переводить юзера на максимальное или минимальное значение? Ведь это исключительные случаи, врятле кто-то руками будет передавать не валидное значение.


    1. mlnewton
      05.05.2016 12:06
      +1

      Спасибо за полезную информацию, учтём)


  1. impwx
    05.05.2016 11:58
    +2

    Зачем вы используете $index? У вас каждый элемент массива равен $index-1, дубликатов не будет — можно было бы взять непосредственно num и не использовать track by.

    В scope объявлено свойство change, которое нигде не используется.

    Стилизовать и локализовать нельзя.

    Если страниц вдруг будет действительно много, покажется весь список, хотя обычно промежуточные значения между текущей страницей и краями скрывают, вот так:



    У вас получился компонент для решения вашей конкретной задачи, но это не библиотека для широкого использования.


    1. mlnewton
      05.05.2016 12:09

      Спасибо за полезную информацию, учтём)


  1. bromzh
    05.05.2016 12:00
    +1

    Если у Вас есть замечания/предложения как сделать лучше с удовольствием выслушаем.

    1) Бегом смотреть styleguide.
    2) Зачем использовать $watch и $scope там, где не надо?
    3) Со стороны UI посмотрите на эту реализацию
    4) Никакой гибкости. Например, Spring умеет отдавать коллекции в pagable-виде. Данные о странице передаются в гет-параметрах. Хочется автоматизировать этот процесс.


    5) Почему не angular 2?


    1. mlnewton
      05.05.2016 12:11
      -2

      Спасибо за полезную информацию, учтём)

      5) Как-то сложилось исторически, обязательно попробуем angular 2


      1. Ohar
        05.05.2016 14:51

        А зачем вы публикуете устаревшее говно историческое наследие вместо следования современным тенденциям?


        1. mlnewton
          05.05.2016 17:07

          ответ на этот вопрос я уже дал выше, возможно кому-то пригодится ;)


          1. stas404
            05.05.2016 22:13
            +7

            Вы забыли дописать «Спасибо за полезную информацию, учтём» )


            1. mlnewton
              06.05.2016 13:07
              -1

              Спасибо за полезную информацию, учтём)