Angularjs分页指令

第一次写博客,有不对的地方请指正!
在项目中许多页面都用到了分页,然后每个页面都有许多重复的分页代码,于是自己写了一份简易的分页指令,简化页面的代码,且容易维护,写在博客中当做备份,方便以后查阅。
以下是定义指令及其应用的步骤:
1.指令定义
定义一个js文件,page-directive.js,用来写分页的指令代码,这个文件中包含了分页的模板,以下是js文件中的所有代码:

'use strict';
(function () {
  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('pageInit', ['template/pageInit/pageInit.html'])
    .directive('pageInit',['pageinitTemplate', function(pageinitTemplate) {
      return {
        restrict   : 'AE',
        templateUrl: function (tElement, tAttrs) {
          return tAttrs.templateUrl || pageinitTemplate.getPath();
        },
        replace    : true,
        scope      : {
          pageData        : '=',
          prev            : '&',
          next            : '&',
          loadPage        : '&'
        },
        link            : function(scope, element, attrs) {
          scope.on_prev = function() {
            if(scope.prev) {
              scope.prev();
            }
          };
          scope.on_next = function() {
            if(scope.next) {
              scope.next();
            }
          };
          scope.on_loadPage = function(page) {
            scope.inpage = undefined;
            if(scope.loadPage) {
              scope.loadPage({page: page});
            }
          };
        }
      };
    }])
    .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);

2.分页样式控制
建议写在单独的.css文件中,首先新建pageSync.css文件,以下是具体样式

.pagination-main {
  display: inline-block;
  padding-left: 0;
  margin: 0 0;
  border-radius: 4px;
  vertical-align: middle;
}
.pagination-main li.prev-page > a {
  border: 0;
}
.pagination-main li.next-page > a {
  border: 0;
  border-left: 1px;
  margin-left: 0;
}
.pagination-main li.first-page > a {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
.pagination-main li.last-page > a {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
.pagination-main li div {
  width: 80px;border: 1px solid #DDDDDD;background-color: #ffffff;float: left;padding: 0;
}
.pagination-main li.skip-page input[type='text'] {
  width: 24px;height: 20px;border: 0;text-align: center;
}
.pagination-main li.skip-page input[type='button'] {
  padding: 0 4px 1px 10px;border: 0;border-left: 1px solid #dddddd;background-color: #ffffff
}
.pagination-main li.data-num > a {
  border: 0;
  margin-left: 0;
}
.pagination-main > li {
  display: inline;
}
.pagination-main > li:first-child > a,
.pagination-main > li:first-child > span {
  /*margin-left: 0;
  border-top-left-radius: 4px;
  border-bottom-left-radius: 4px;*/
}
.pagination-main > .active > a,
.pagination-main > .active > span,
.pagination-main > .active > a:hover,
.pagination-main > .active > span:hover,
.pagination-main > .active > a:focus,
.pagination-main > .active > span:focus {
  z-index: 2;
  color: #fff;
  cursor: default;
  background-color: #428bca;
  border-color: #428bca;
}
.pagination-main > li > a,
.pagination-main > li > span {
  position: relative;
  float: left;
  /*padding: 6px 12px;*/
  padding: 1px 8px;
  margin-left: -1px;
  line-height: 1.42857143;
  color: #428bca;
  text-decoration: none;
  background-color: #fff;
  border: 1px solid #ddd;
}
.pagination-main > .disabled > span,
.pagination-main > .disabled > span:hover,
.pagination-main > .disabled > span:focus,
.pagination-main > .disabled > a,
.pagination-main > .disabled > a:hover,
.pagination-main > .disabled > a:focus {
  color: #999;
  cursor: not-allowed;
  background-color: #fff;
  border-color: #ddd;
}

3.分页查询方法
我在factory中自定义了分页查询的方法,共用,方便代码的维护。在angular中与后台的交互默认是异步的,我这里写成同步查询了,首先定义js文件pageSync.service.js,以下是factory的全部内容:

'use strict';
angular.module('app').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);
      }
      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;
  };
  // 项目中table的高度是根据浏览器窗口的高度计算的来的,是动态的
  // 因为要把分页固定在table最下方,所以无数据的用空行进行代替
  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);
      }
    }
  }
}]);

4.使用指令

1.页面上的代码:

我的代码中分页是写在table中的tfoot里面了,prev()、next()、loadPage(page)均为在页面对应的controller中定义的方法

<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="!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="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-init page-data="pageData" prev="prev()" next="next()" load-page="loadPage(page)"></page-init>
      </div>
    </td>
  </tr>
</tfoot>
</table>
2.controller中的代码

首先要引用factory,将PageSync在controller中引用,如下:

angular.module('app').controller('MyCtrl', function(PageSync) {});

在分页查询之前要做一些准备工作:

//pageData中设置分页数据集合、总页数、页码集合、数据总数,loadTime为自定义的参数,用来记录时间状态(访问数据前及返回数据后)
$scope.pageData = {rowCollectionPage: [], totalPage: 1, currentPage:1, pages: [],count: 0, loadTime: 'before'};
// 这里用来计算table的高度,根据实际情况来。
$scope.tabHeight = $scope.height-48-37-10-42-5;
// 计算实际中一页有多少行数据
$scope.pageSize = parseInt(($scope.tabHeight-15-34-34-39)/34);

然后再controller中写如下的方法

// 分页查询
$scope.load = function(row) {
  $scope.surgeonPageData.rowCollectionPage = Common.setPageRow([],$scope.pageSize);
  $scope.noSurgeonData = false;
  $scope.surgeonPageData.loadTime = 'before';
  PageSync.load(url, $scope.pageData.currentPage, $scope.pageSize).then(function(data) {
    $scope.pageData = data;
    if(($scope.pageData.loadTime=='after'&& $scope.pageData.count==0) || $scope.pageData.loadTime=='before') {
      $scope.noTableData = true;
    }
  });
};
// 下一页
$scope.next = function() {
  if ($scope.pageData.currentPage < $scope.pageData.totalPage) {
    PageSync.next(url, $scope.pageData.currentPage, $scope.pageSize).then(function(data) {
      $scope.pageData = data;
    });
  }
};
// 上一页
$scope.prev = function() {
  if ($scope.pageData.currentPage > 1) {
    PageSync.prev(url, $scope.pageData.currentPage, $scope.pageSize).then(function (data) {
      $scope.pageData = data;
    });
  }
};
// 点击页码跳转
$scope.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) {
    alert('请填写跳转页码!');
  } else if(intPage <= 0 || intPage > $scope.pageData.totalPage) {
    alert('跳转页码应大于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;
    });
  }
};

5.结果
最终的实现效果如下图:
这里写图片描述

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值