ngTbale真分页实现排序、搜索等功能
一. 真分页表格基础
1. 需求:分页,排序,搜索都是需要发API到服务端。
2. JS实现代码:
getStorage是localStorage一个工具方法,可以自己写这个方法。
API参数如下:
{
limit: initItemCountPerPage,
index: options1.page,
sortKey: options1.sortKey ? encodeURIComponent(options1.sortKey) : '',
sortType: options1.sortType ? options1.sortType: '',
searchWord: ''
}
angular.module('newApp') .factory('ListTableSV', ['$timeout', 'ngTableParams', 'getStorage', function ($timeout, ngTableParams, getStorage) { var store = getStorage('localStorage'); /** * 创建表格 * @param options1 * @param options2 * @returns {ngTableParams|*} */ function createListTable(options1, options2) { var listTable = new ngTableParams(options1, { counts: options2.counts, getData: function ($defer, params) { if (!listTable.isNotFisrtLoadData) { listTable.apiParams = initApiParams(options1); } listTable.isNotFisrtLoadData = true; options2.getData(listTable.apiParams).then(function (data) { listTable.resetCheckboxes(); var resData = data.data.data; var onDataResult = options2.onDataResult; if (onDataResult) { onDataResult(resData); } var items = resData.items; var dataPreprocessFunc = options2.dataPreprocessFunc; if (dataPreprocessFunc) { dataPreprocessFunc(items); } var totalCount = resData.totalCount ? resData.totalCount : 0; params.items = (items && totalCount) ? items : []; listTable.calculatePages(totalCount); params.total(totalCount); $defer.resolve(params.items); return; }, function () { params.items = []; var totalCount = 0; listTable.calculatePages(totalCount); params.total(totalCount); $defer.resolve(params.items); return; }); } }); listTable.tableName = options1.tableName; listTable.titles = options1.titles; listTable.getItemId = options2.getItemId; listTable.toFirstPageAndReload = function () { if (listTable.page() == 1) { listTable.reload(); } else { listTable.toPage(1); } }; return listTable; }; function initApiParams(options1) { var STORAGE_PAGESIZE_KEY = getKeyForStoragePageSize(options1); if (store.get(STORAGE_PAGESIZE_KEY)) { var initItemCountPerPage = store.get(STORAGE_PAGESIZE_KEY)['value']; } else { var initItemCountPerPage = options1.count; } return { limit: initItemCountPerPage, index: options1.page, sortKey: options1.sortKey ? encodeURIComponent(options1.sortKey) : '', sortType: options1.sortType ? options1.sortType: '', searchWord: '' }; } /** * 初始化排序功能 * @param listTable */ function initSort(listTable, options1) { listTable.sortClickIndex = 0; listTable.sortClickDelayIndex = 0; listTable.sortDelay = 750; listTable.nextSortType = function () { return listTable.sortParams.type == 'asc' ? 'desc' : 'asc'; }; listTable.isColumnSorting = function (key) { return listTable.sortParams.key == key; }; listTable.isColumnSortingByASC = function (key) { return listTable.isColumnSorting(key) && listTable.sortParams.type == 'asc'; }; listTable.isColumnSortingByDESC = function (key) { return listTable.isColumnSorting(key) && listTable.sortParams.type == 'desc'; }; listTable.resetSortParams = function () { listTable.sortParams = { key: options1.sortKey ? options1.sortKey : '', type: options1.sortType ? options1.sortType : '' }; }; listTable.toSorting = function (key, type) { listTable.sortClickIndex ++; listTable.sortParams.key = key; listTable.sortParams.type = type; $timeout(function() { listTable.sortClickDelayIndex ++; if (listTable.sortClickIndex === listTable.sortClickDelayIndex) { listTable.sortClickIndex = 0; listTable.sortClickDelayIndex = 0; listTable.apiParams.sortKey = encodeURIComponent(key); listTable.apiParams.sortType = type; listTable.toFirstPageAndReload(); } }, listTable.sortDelay); } listTable.resetSortParams(); }; /** * 初始化条目选择框 * @param listTable * @param withCheckboxes * @returns {*} */ function initCheckboxes(listTable, withCheckboxes) { if (withCheckboxes) { listTable.toggleCheckAll = function () { var checkedCount = listTable.checkedIds().length; if (checkedCount == listTable.items.length) { listTable.deselectAll(); } else { listTable.selectAll(); } }; listTable.selectAll = function () { listTable.resetCheckboxes(); listTable.checkboxes.selectAll = true; for (var index in listTable.items) { listTable.checkboxes.items[listTable.getItemId(listTable.items[index])] = true; } }; listTable.deselectAll = function () { listTable.resetCheckboxes(); listTable.checkboxes.selectAll = false; for (var index in listTable.items) { listTable.checkboxes.items[listTable.getItemId(listTable.items[index])] = false; } }; listTable.checkedIds = function () { var ids = []; for (var index in listTable.items) { var id = listTable.getItemId(listTable.items[index]); if (listTable.checkboxes.items[id]) { ids.push(id); } } listTable.checkboxes.selectAll = listTable.items ? (listTable.items.length == ids.length) : false; return ids; } listTable.resetCheckboxes = function () { listTable.checkboxes = { selectAll: false, items: {} }; }; } else { listTable.resetCheckboxes = function () { } } listTable.resetCheckboxes(); return listTable; }; /** * 初始话分页功能 * @param listTable 表格 * @private */ function initPagination(listTable, options1) { var STORAGE_PAGESIZE_KEY = getKeyForStoragePageSize(options1); if (store.get(STORAGE_PAGESIZE_KEY)) { listTable.count(store.get(STORAGE_PAGESIZE_KEY)['value']); } if (options1.page) { listTable.page(options1.page); } listTable.editCount = listTable.count(); listTable.toCount = function (count) { var currentCount = listTable.count(); if (currentCount != count) { listTable.count(count); listTable.apiParams.index = 1; listTable.apiParams.limit = count; } }; listTable.prePage = function () { var page = listTable.page(); if (page > 1) { listTable.page(page - 1); listTable.apiParams.index = page - 1; } }; listTable.nextPage = function () { var page = listTable.page(); if (page < Math.ceil(1.0 * listTable.total() / listTable.count())) { listTable.page(page + 1); listTable.apiParams.index = page + 1; } }; listTable.toPage = function (page) { var currentPage = listTable.page(); if (currentPage != page) { listTable.page(page); listTable.apiParams.index = page; } }; listTable.calculatePages = function (totalCount) { var itemCountPerPage = listTable.count(); store.set(STORAGE_PAGESIZE_KEY, { 'value': itemCountPerPage }); var totalPage = Math.ceil(1.0 * totalCount / itemCountPerPage); var currentPage = Math.max(1, Math.min(listTable.page(), totalPage)); listTable.pages = calculateTablePages(currentPage, totalPage); } }; function getKeyForStoragePageSize(options1) { return 'list_table_page_size@' + options1.tableName; }; function calculateTablePages(currentPage, totalPage) { if (totalPage == 0) { return []; } var end = Math.min(9, totalPage); var pages = [currentPage]; while (pages.length < end) { var pre = pages[0] - 1; var next = pages[pages.length - 1] + 1; if (pre >= 1) { pages.unshift(pre); } if (next <= totalPage) { pages.push(next); } } return pages; }; function init(options1, options2) { var listTable = createListTable(options1, options2); initSort(listTable, options1); initCheckboxes(listTable, options1.withCheckboxes); initPagination(listTable, options1); return listTable; }; return { init: init, }; }]);
2. html分页代码
<div class="ng-cloak dahuo-pagination" ng-if="params.pages.length > 0"> <div class="col-lg-6"> <div class="dataTables_info" role="status" aria-live="polite" ng-if="params.pages.length > 0"> {{ params.count() * (params.page() - 1) + 1 }}~ {{ params.count() * (params.page() - 1) + params.data.length }}条,共{{ params.total() }}条记录 </div> </div> <div class="col-lg-6 pagination2" style="margin-bottom: 40px"> <div class="dataTables_paginate paging_simple_numbers"> <ul class="pagination ng-table-pagination"> <li><a href="" ng-click="params.prePage()">上一页</a></li> <li ng-repeat="page in params.pages" ng-class="{'active' : page == params.page()}"> <a href="" ng-click="params.toPage(page)">{{ page }}</a> </li> <li><a href="" ng-click="params.nextPage()">下一页</a></li> </ul> </div> <div class="col-lg-3 pull-right"> <select class="select form-control" ng-model="params.editCount" ng-change="params.toCount(params.editCount)" style="padding: 6px; margin-top: 2px;min-width: 80px;margin-right: 10px" ng-options="size for size in params.settings().counts"> </select> </div> </div> </div>
3. 说明:
基本实现了分页,搜索,排序(仅仅支持单个排序)等功能。搜索和排序会返回第一页。
二. 使用方法
服务端应该返回结果{data:{data: {items: [{name1: ...}, {...}]}}};
1. html中Table部分的代码
没有什么其他说的,这么写就行了。
<div class="table-responsive"> <table ng-table="productsTable" class="table trans-table table-hover text-left dahuo-table" template-pagination="layouts/pagination_v3.html" width="100%"> <thead> <tr> <th width="5%" class="dahuo-table-header-th text-center" header="'ng-table/headers/checkbox.html'"> <span class="list-checkbox"> <input type="checkbox" ng-model="productsTable.checkboxes.selectAll" ng-disabled="productsTable.items.length < 1" ng-click="productsTable.toggleCheckAll()"/> <span></span> </span> </th> <th width="15%" ng-repeat="title in productsTable.titles" ng-class="{'sort': title.sortable}" ng-click="productsTable.toSorting(title.key, productsTable.nextSortType())"> {{ title.name }} <li class="fa pull-right" ng-if="title.sortable" ng-class="{'fa-sort-asc': productsTable.isColumnSortingByASC(title.key), 'fa-sort-desc': productsTable.isColumnSortingByDESC(title.key), 'fa-unsorted': !productsTable.isColumnSorting(title.key)}" aria-hidden="true" ng-style="{'color' : (!productsTable.isColumnSorting(title.key) ? '#c9c9c9' : '')}"></li> </th> </tr> </thead> <tbody> <tr ng-repeat="item in $data"> <td width="5%" header="'ng-table/headers/checkbox.html'" class="str-checkbox, dahuo-table-body-th text-center"> <span class="list-checkbox"> <input type="checkbox" ng-model="productsTable.checkboxes.items[item.id]" disabled/> <span></span> </span> </td> <td>{{item.name1}}</td> <td>{{item.name2}}</a></td> <td>{{item.name3}}</td> <td>{{item.name4}}</td> <td>{{item.name5}}</td> </tr> <tr style="height: 100px" ng-if="$data.length < 1"> <td colspan="6" class="text-center">暂时没有数据</td> </tr> </tbody> </table> </div>
2. Controller调用
DS是发送API的一个服务。这里可以改成自己要发的API,改的时候注意使用$q服务返回值。
$scope.productsTable = new ListTableSV.init( { tableName:'fund.update.list.products', titles:[ {key: 'name1', name: "名字1", sortable: true}, {key: 'name2', name: "名字2", sortable: true}, {key: 'name3', name: "名字3", sortable: true}, {key: 'name4', name: "名字4", sortable: true}, {key: 'name5', name: "名字5", sortable: true}, ], withCheckboxes: true, page: 1, count: 25, sortKey: 'name1', sortType: 'desc' }, { counts: [10, 25, 50, 100], getData: function(apiParams) { return DS.simplelist(apiParams); }, getItemId: function(item) { return item.id; } } );
三. 搜索的调用方法
很好调用,就两行代码,先更改API,在reload。
$scope.productsTable.apiParams.searchWord = encodeURIComponent($scope.keyword);
$scope.productsTable.toFirstPageAndReload();