Angularjs分页指令(优化)

之前写了一个简单的Angularjs的分页指令,在后期工作量减少后对分页做了一些优化,将分页数据的查询及页码跳转都写在了指令内部,减少了controller中的代码量,使用更加简单。

指令定义

定义指令的module中糅合了指令的定义及查询数据的factory,将页码跳转的方法写在了指令中,指令使用的模板和factory中的查询方法都没有变化,只是factory的位置及使用方式发生了一些变化,具体看代码:

'use strict';
(function () {
  var forEach = angular.forEach;
  angular.module('template/pageInit/pageInit.html', []).run([
    '$templateCache',function($templateCache) {
      $templateCache.put('template/pageInit/pageInit.html',
        '<ul class="pagination-main">\n'+
        '  <li class="prev-page" ng-class="{disabled:pageData.currentPage==1}" title="首页">\n'+
        '    <a href="javascript:void(0);" ng-click="on_loadPage(1)"><span class="fa fa-fast-backward"></span></a>\n'+
        '  </li>\n'+
        '  <li class="prev-page" ng-class="{disabled:pageData.currentPage==1  }">\n'+
        '    <a href="javascript:void(0);" ng-click="on_prev()" title="上一页"><span class="fa fa-step-backward"></span></a>\n'+
        '  </li>\n'+
        '  <li class="data-page" ng-repeat="page in pageData.pages" ng-class="{\'first-page\': page==1, \'last-page\': page==pageData.totalPage}">\n'+
        '    <a ng-if="page!=\'...\'" href="javascript:void(0);" ng-class="{\'bg-custom\': page==pageData.currentPage}" ng-click="on_loadPage(page, tabData)">{{ page }}</a>\n'+
        '    <a ng-if="page==\'...\'" href="javascript:void(0);" ng-class="{\'bg-custom\': page==pageData.currentPage}" ng-click="">{{ page }}</a>\n'+
        '  </li>\n'+
        '  <li class="next-page" ng-class="{disabled:pageData.currentPage==pageData.totalPage}">\n'+
        '    <a href="javascript:void(0);" ng-click="on_next()" title="下一页"><span class="fa fa-step-forward"></span></a>\n'+
        '  </li>\n'+
        '  <li class="skip-page"><div><input type="text" placeholder="" ng-model="inpage">\n'+
        '    <input type="button" value="跳转" ng-click="on_loadPage(inpage)"></div>\n'+
        '  </li>\n'+
        '  <li class="data-num"><a class="cursor-text" href="#"><span>共{{pageData.count}}条</span></a></li>\n'+
        '</ul>\n'+
        ''
      );
    }
  ]);
  angular.module('pageInit2', ['template/pageInit/pageInit.html'])
    .factory('PageSync', ['$http', '$q', function Page($http, $q) {
      var rowCollectionPage = [];
      var totalPage = 1;
      var pages = [];
      var endPage = 1;
      var load = function(url, currentPage, pageSize,deferred) {
        var json = {rowCollectionPage: [], totalPage: 1, currentPage:currentPage ? currentPage:1, pages: []};
        $http.get(url).success(function(rows) {
          rowCollectionPage = setPageRow(rows.list, pageSize);
          // 获取总页数
          totalPage = Math.ceil(rows.count / pageSize);
          endPage = totalPage;
          // 生成数字链接
          if (totalPage <= 7) {
            pages = getPagesLow(totalPage);
          } else {
            pages = getPagesHigh(currentPage, totalPage);
          }
          /*if(totalPage <= 1) {// 总页数就一页的时候这里放入一个空对象代替的是分页那一行
           rowCollectionPage.push({});
           }*/
          json.rowCollectionPage = rowCollectionPage;
          json.totalPage = totalPage==0 ? 1 : totalPage;
          json.currentPage = currentPage;
          json.pages = pages;
          json.count = rows.count;
          json.pageSize = pageSize;
          /**
           * 自定义字段,初始化的时候为before,只要经过该分页方法,则字段值变为after
           * before表示未经过该分页方法,after表示经过该分页方法,
           * 前台页面加载的规则:为before时表示表格无数据,为after且pataData.count==0时无数据,否则视为有数据
           */
          json.loadTime = 'after';
          deferred.resolve(json);
        });
        return deferred.promise;
      };
      // 总页数小于等于7时 显示所有的页数
      var getPagesLow = function(totalPage) {
        var temp = [];
        for (var i=1; i<totalPage+1; i++) {
          temp.push(i);
        }
        return temp;
      };
      // 总页数大于7时 根据当前页获取7个页码数
      var getPagesHigh = function(currentPage, totalPage) {
        var temp = [];
        if (currentPage < 4) {
          temp = [1, 2, 3, 4, 5, '...', totalPage];
        } else if ((totalPage - currentPage) <= 3) {
          temp = [
            totalPage - 6, totalPage - 5, totalPage - 4,
            totalPage - 3, totalPage - 2, totalPage - 1, totalPage
          ];
        } else {
          temp = [
            currentPage - 2, currentPage - 1, currentPage,
            currentPage + 1, currentPage + 2, '...', totalPage
          ];
        }
        return temp;
      };
      var setPageRow = function(rowArr, pageSize) {
        var temp = [];
        if (rowArr != undefined) {
          for (var i = 0; i < rowArr.length; i++) {
            temp.push(rowArr[i]);
          }
          for (var j = 0; j < pageSize - rowArr.length; j++) {
            temp.push({});
          }
        } else {
          for (var k = 0; k < pageSize; k++) {
            temp.push({});
          }
        }
        return temp;
      };
      return {
        load: function(url, currentPage, pageSize) {
          var deferred = $q.defer();
          url += '&' + currentPage + '&' + pageSize;
          return load(url, currentPage, pageSize, deferred);
        },
        next: function(url, currentPage, pageSize) {
          var deferred = $q.defer();
          if (currentPage < endPage) {
            currentPage++;
          }
          url += '&' + currentPage + '&' + pageSize;
          return load(url, currentPage, pageSize, deferred);
        },
        prev: function(url, currentPage, pageSize) {
          var deferred = $q.defer();
          currentPage--;
          url += '&' + currentPage + '&' + pageSize;
          return load(url, currentPage, pageSize, deferred);
        },
        loadPage: function(url, currentPage, pageSize, page) {
          var deferred = $q.defer();
          if (currentPage != page) {
            currentPage = page;
            url += '&' + currentPage + '&' + pageSize;
            return load(url, currentPage, pageSize, deferred);
          }
        }
      }
    }])
    .directive('pageInits', ['pageinitTemplate', 'PageSync', '$rootScope', function(pageinitTemplate, PageSync, $rootScope) {
      return {
        restrict   : 'AE',
        templateUrl: function (tElement, tAttrs) {
          return tAttrs.templateUrl || pageinitTemplate.getPath();
        },
        replace    : true,
        scope      : {
          queryUrl        : '=queryUrl',
          condition       : '=condition',
          pageData        : '=pageData',
          pageSize        : '=pageSize'
        },
        link            : function(scope, element, attrs) {
          scope.arr = [];// 存放需要监控属性值变化的变量,根据是否变化进行查询分页数据与否
          scope.valArr = [];// 存放查询条件变量值
          // 分页时无数据用空行代替,使分页始终在页面底部
          var setPageRow = function(rowArr, pageSize) {
            var temp = [];
            if (rowArr != undefined) {
              for(var i=0; i<rowArr.length; i++) {
                temp.push(rowArr[i]);
              }
              if (rowArr.length < pageSize) {
                for(var j=0; j<pageSize-rowArr.length; j++) {
                  temp.push({});
                }
              }
            }
            return temp;
          };
          // 获取分页的url
          var initUrl = function() {
            var result = scope.queryUrl;
            var condArr = scope.valArr;
            for(var i = 0; i < condArr.length; i++) {
              if(i == 0) {
                result += condArr[i];
              } else {
                result += '&' + condArr[i];
              }
            }
            return result;
          };
          var url = '';
          // 查询数据
          var load = function() {
            var pageSize = scope.pageData.pageSize = scope.pageSize ? scope.pageSize : 10;
            scope.pageData.rowCollectionPage = setPageRow([],pageSize);
            scope.pageData.noTableData = false;
            scope.pageData.loadTime = 'before';
            PageSync.load(url, scope.pageData.currentPage, pageSize).then(function(data) {
              scope.pageData = data;
              if((scope.pageData.loadTime=='after'&& scope.pageData.count==0) || scope.pageData.loadTime=='before') {
                scope.pageData.noTableData = true;
              }
            });
          };
          // 循环拿到分页的查询条件
          for(var key in scope.condition) {
            scope.arr.push('condition.'+key);
          }
          scope.arr.push('pageData.loadTime');
          // 监控分页的查询条件,并得到分页查询条件所对应的值
          scope.$watchGroup(scope.arr, function(newVal) {
            if(newVal[newVal.length-1] != 'after') {
              scope.valArr = [];
              forEach(newVal, function(val, index) {
                if(index != newVal.length-1) {
                  scope.valArr.push(val);
                }
              });
              url = initUrl();
              load(scope);
            }
          });

          // 上一页
          scope.on_prev = function() {
            if (scope.pageData.currentPage > 1) {
              PageSync.prev(url, scope.pageData.currentPage, scope.pageSize).then(function (data) {
                scope.pageData = data;
              });
            }
          };
          // 下一页
          scope.on_next = function() {
            if (scope.pageData.currentPage < scope.pageData.totalPage) {
              PageSync.next(url, scope.pageData.currentPage, scope.pageSize).then(function(data) {
                scope.pageData = data;
              });
            }
          };
          // 跳转
          scope.on_loadPage = function(page) {
            scope.inpage = undefined;
            var intPage;
            if (typeof page == 'string') {
              if(page!="") {
                intPage = parseInt(page, 10);
              } else {
                intPage = 0;
              }
            } else {
              intPage = page;
            }
            if (scope.pageData.totalPage <= 1) {

            } else if (intPage == undefined || intPage == null) {
              $rootScope.lxAlert['danger']('请填写跳转页码!');
            } else if(intPage <= 0 || intPage > scope.pageData.totalPage) {
              $rootScope.lxAlert['danger']('跳转页码应大于0,小于总页数'+scope.pageData.totalPage);
            } else if (scope.pageData.currentPage != page) {
              PageSync.loadPage(url, scope.pageData.currentPage, scope.pageSize, page).then(function (data) {
                scope.pageData = data;
              });
            }
          };
        }
      };
    }])
    .provider('pageinitTemplate', function () {
      var templatePath = 'template/pageInit/pageInit.html';
      this.setPath = function (path) {
        templatePath = path;
      };

      this.$get = function () {
        return {
          getPath: function () {
            return templatePath;
          }
        };
      };
    });
}).call(window);

分页样式控制

参考我的另一篇文章Angularjs分页指令,样式一样。

使用指令

页面上的代码
<table>
<thead>
  <tr>
    <th>序号</th>
    <th>列名1</th>
    <th>列名2</th>
    <th style="width: 150px;text-align: center;">操作</th>
  </tr>
</thead>
<tbody>
  <tr ng-if="!pageData.noTableData" ng-repeat="row in pageData.rowCollectionPage">
    <td>{{!!row.id ? $index+1+(pageData.currentPage-1)*pageSize : ''}}</td>
    <td>{{row.args1}}</td>
    <td>{{row.args2}}</td>
    <td style="text-align: center;"><a href='#'>修改</a></td>
  </tr>
  <tr ng-if="pageData.noTableData" ng-repeat="data in pageData.rowCollectionPage">
    <td ng-if="$index == 0" colspan="4" style="text-align: center;">没有数据!</td>
    <td ng-if="$index != 0" colspan="4"></td>
  </tr>
  </tbody>
<tfoot>
  <tr>
    <td style="text-align: center;" colspan="6">
      <div>
        <page-inits query-url="queryUrl" condition="condition" page-data="pageData" page-size="pageSize"></page-inits>
      </div>
    </td>
  </tr>
</tfoot>
</table>

与上一篇的变化:该指令定义是将noTableData写在了pageData中,是pageData的一个元素,页面上与之相应的改变成pageData.noTableData(noTableData用来判断当前页是否存在数据);分页名称改变成pageInits,页面上指令的使用与之相应改变。

controller中的代码

这里不需要再引用PageSync(factory),是在定义指令时引用的,且factory写在了指令所在的module中。
使用指令时controller中不需要再写分页查询及跳转的方法,但必须把分页所需的项全部配置对才可正确的进行分页(目前做的兼容性可能会很差,配置不对会报错或不执行查询分页)。

$scope.height = Common.getWindowsHeight();
// 初始化分页信息
$scope.pageData = {rowCollectionPage: [], totalPage: 1, currentPage:1, pages: [],count: 0, loadTime: 'before',noTableData: false};
// 计算每页的行数
$scope.tabHeight = $scope.height-48-37-10-42-5;
$scope.pageSize = parseInt(($scope.tabHeight-15-34-39)/34);
// 查询路由接口(不带参数,具体的需要在指令中根据特定规则生成)
$scope.queryUrl = '/api/disease/getPageData/';
// 监控查询条件:对中文查询条件做了encode操作,防止到后台乱码,后台再做uncode操作即可。
$scope.$watch('name', function() {
  if($scope.name== '') {
    $scope.codeName = undefined;
  } else {
    $scope.codeName = encodeURI(encodeURI($scope.name));
  }
});
$scope.setPageRow = function(rowArr, pageSize) {
  var temp = [];
  if (rowArr != undefined) {
    for(var i=0; i<rowArr.length; i++) {
      temp.push(rowArr[i]);
    }
    if (rowArr.length < pageSize) {
      for(var j=0; j<pageSize-rowArr.length; j++) {
        temp.push({});
      }
    }
  }
  return temp;
};
// 查询分页数据:进入页面后自动查询
$scope.load = function() {
  $scope.condition= {type: 'all', name: $scope.codeName};
  $scope.pageData.rowCollectionPage = $scope.setPageRow([],$scope.pageSize);
  $scope.pageData.noTableData = false;
  $scope.pageData.loadTime = 'before';
};
$scope.load();
// 点击页面查询按钮
$scope.loadClick = function() {
  $scope.condition= {type: 'all', name: $scope.codeName};
  $scope.pageData.currentPage=1;
  $scope.pageData.noTableData = false;
  $scope.pageData.loadTime = 'before';
};
// 点击页面重置按钮
$scope.reset = function() {
  $scope.name= undefined;
  $scope.condition= {type: 'all', name: undefined};
  $scope.pageData.noTableData = false;
  $scope.pageData.loadTime = 'before';
};

{rowCollectionPage: [], totalPage: 1, currentPage:1, pages: [],count: 0, loadTime: ‘before’,noTableData: false};
在pageData中rowCollectionPage是用来存放当前页的数据,包括无数据时的空行;totalPage表示分页总页数;currentPage表示当前页;pages表示当前分页展示的所有页码数;count表示数据总数,这些好理解。
然后就是loadTime和noTableData,这2个参数是我根据需求在项目开发中自定义的,可以根据表面意思去理解。loadTime:加载时间,有before和after两个值,表示请求数据的前后,会在指令中被监控属性值的变化情况,在加载页面时首先查询一下分页数据,这时loadTime会变为after,用在load、loadClick、reset等方法中(这里loadTime是必须要配置的),定义为$scope.pageData.loadTime=’before’,指令会监控到loadTime的变化然后去请求分页查询,在然后查询后又会变为after,往复循环。noTableData:无表格数据,用于调整页面的展示,在请求分页之前是无数据的,会用空行填充当前页,默认定义为false,然后根据你请求返回的数据情况,有数据则为false,页面用数据加空行(若数据不能填满页面)填充,无数据则为true,页面首行提示无数据,下面用空行填充。
上面的解释可能有些不清楚,具体生成的效果与另一篇文章Angularjs分页指令相同,可以写代码看下效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值