前言
上次寫了一個可拖動列表的插件,但除了這個特點沒什么優點了,接下寫的是我們常用的Bootstrap-table表格插件
正文
官網:https://bootstrap-table.com/
有兩個翻譯API的網址:
https://blog.csdn.net/S_clifftop/article/details/77937356?locationNum=3&fps=1
https://blog.csdn.net/mrczr/article/details/64441265
在使用時需要引入如下幾個文件:
bootstrap.min.css
bootstrap-table.css
jquery.js
bootstrap.js
bootstrap-table.js
bootstrap-table-zh-CN.js(中文插件)
客戶端分頁例如下:
// 首先銷毀表格 $('#fwfx_tb').bootstrapTable('destroy'); // 初始化表格,動態從服務器加載數據 $('#fwfx_tb').bootstrapTable({ pagination: true, //啟動分頁 striped: true, //設置為 true 會有隔行變色效果 cache: false, //是否使用緩存,默認為true,所以一般情況下需要設置一下這個屬性(*) pageSize: 20,//初始頁記錄數 sortable: true, //排序 pageList: [10,20], //記錄數可選列表 smartDisplay: false, //程序自動判斷顯示分頁信息 columns: [{ title: '序號', align: 'center', halign: 'center', formatter: function (value, row, index) { return index + 1; } }, { field: 'name', title: '服務名', align: 'center', sortable:true //排序 }, { field: 'sum', title: '金額', align: 'center' }, { field: 'PV', title: '訪問量', align: 'center' } data: tableData });
服務器端分頁例如下:
$('#user_content_tab').bootstrapTable('destroy');
// 初始化表格,動態從服務器加載數據
$('#user_content_tab').bootstrapTable({
url: "admin/query",
method: 'post',
sidePagination: 'server', //表示服務端請求
queryParams:logUl,//請求服務器時所傳的參數
ajaxOptions:{ //提交ajax請求時的附加參數
headers: {
'token': '94564375541867846'//這里傳的token是根據你的前后台交互情況
}
},
toolbar : '#toolbar', // 工具按鈕用哪個容器
pagination: true, //默認為false,表格的底部工具欄不會顯示分頁條
queryParamsType:'',//查詢參數組織方式,必須設置為空,否則沒有頁碼params.pageNumber
striped: true, //設置為 true 會有隔行變色效果
pageSize: 20, //每頁顯示行數
pageList:[10,20,50],
maintainSelected: true, //在點擊分頁按鈕或搜索按鈕時,將記住checkbox的選擇項
smartDisplay: false, //程序自動判斷顯示分頁信息
clickToSelect: true, //是否啟用點擊選中行
toolbarAlign: 'right', //指定 toolbar 水平方向的位置
uniqueId: 'userId', //為每一行指定唯一標識符
idField: 'userId', //指定主鍵列
paginationDetailHAlign:'right',//指定分頁詳細信息在水平方向的位置
columns: [{
title: '序號',
align: 'center',
halign: 'center',
formatter: function (value, row, index) {
var options = $table.bootstrapTable('getOptions');
return options.pageSize * (options.pageNumber - 1) + index + 1;
}
},{
field: 'userId',
title: '用戶ID',
align: 'center',
},
{
field: 'username',
title: '用戶名稱',
align: 'center'
},
{
field: 'roleName',
title: '角色',
align: 'center'
},
{
field: 'createTime',
title: '創建時間',
align: 'center',
formatter : function(value, row, index) {
return fmtDate(value)
}
},
{
field: 'status',
title: '賬戶狀態',
align: 'center'
},
{
field: 'userId',
title: '操作',
align: 'center',
width: 350,
formatter: operateFormatter//在這里我的目的是添加按鈕
}],
formatNoMatches: function(){
return "沒有相關的匹配結果";
},
formatLoadingMessage: function(){
return "請稍等,正在加載中。。。";
},
responseHandler:function(res){ //加載服務器數據之前的處理程序,可以用來格式化數據,服務器返回的數據要在這里使用
if(res.resCode == "403"){
localStorage.clear();
parent.location.href = location403;
} else if(res.resStatus == 0) {
for(var i = 0; i < res.resData.rows.length; i++) {
if(res.resData.rows[i].status) {
res.resData.rows[i].status = '啟用';
} else {
res.resData.rows[i].status = '禁用';
}
}
var cusData = {//這里的處理數據是根據你前后台交互的數據情況來的 "rows": res.resData.rows,
"total": res.resData.total
}
return cusData;
} else {
toastr.info(res.resMsg);
return;
}
}
});
function logUl(params){
pageNumbers = params.pageNumber;
pageSizes = params.pageSize;
return {
"pageNo": params.pageNumber,
"pageSize": params.pageSize,
"username": queryVal
}
}
function operateFormatter(value, row, index){ //添加按鈕
var rows = JSON.stringify(row);
// 根據傳過來的參數添加不同的class
var classED = 'enabledE';
var classEDVal;
if(row.status == '啟用') {
classED = 'enabledD';
classEDVal = '禁用';
} else {
classED = 'enabledE';
classEDVal = '啟用';
}
// onclick=modif(' + value + "," + rows + "," + index + ')
return [
'<div class="modify operationBtn" title="重置密碼" table-data=' + rows + '><i class="glyphicon glyphicon-pencil"></i>重置密碼</div>',
'<div class="enabled operationBtn '+ classED + '" title="禁用/啟用" table-data=' + rows + '><i class="glyphicon glyphicon-user"></i>' + classEDVal + '</div>',
'<div class="del operationBtn" title="刪除" table-data=' + rows + '><i class="glyphicon glyphicon-trash"></i>刪除</div>'
].join("")
}
拖動列來控制列寬的插件:
引入bootstrap-table-resizable.js和colResizable-1.6.min.js
$("#exampleTable").colResizable({
liveDrag: true,//實時顯示滑動位置
gripInnerHtml: "<div class='grip'></div>",
//draggingClass: "dragging",
postbackSafe: true,//刷新后保留之前的拖拽寬度
headerOnly:true,
resizeMode:"overflow",
//onResize: onSampleResized
});
一些功能實現的樣例:
1.選中
$('#generateClueObjectTable').bootstrapTable('checkBy', { field:"這里是選中行列字段", values:[這里選中行是列字段內的值,可多個]});
只可選中一行,使用check.bs.table事件(當用戶選中一行時觸發的事件)
$('#generateClueObjectTable').on('check.bs.table', function (row,element,input) {
if (_this.addResearchReportTransObjectJudge) {
let selections = $("#generateClueObjectTable").bootstrapTable('getSelections');
if (selections.length > 1) {
$('#generateClueObjectTable').bootstrapTable('uncheck',input[0].dataset.index);
_this.$message.error('只能選擇一個對象');
}
}
});
2.禁止全選操作,例:
check-all.bs.table 全選事件
$('#generateClueObjectTable').on('check-all.bs.table', function (row,element,input) {
if(_this.addResearchReportTransObjectJudge) {
$("#generateClueObjectTable").bootstrapTable('uncheckAll');//阻止全選
}
});
3.為復選框(checkbox)禁用或選中,例:
在復選框(checkbox)列中使用formatter
formatter: function (value, row, index) { return { disabled : true //設置是否可用 checked : true//設置選中 } }
4.在表格中嵌套表格,例:
columns:[{ title: '部門', align: 'left', sortable: false, formatter: function (value, row, index) { return row.deptName; } },{ field: '', title: "<table id=\"statisticTable\" class=\"tables\" style='border:1px solid #bdd5dd;'>" + "<thead><tr>" + "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">狀態</th>" + "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">數量</th>" + "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">自主調研</th>" + "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">上級交辦</th>" + "</tr></thead>" + "</table>", align: 'left', sortable: false, formatter: function (value, row, index) { var table = "<table class='table-keyValue' style='border:1px solid #d0e3e9;'>"; $.each(row.stats, function (i, item) { table += "<tr><td style=\"width:9%;\" class='statisticTableTD '>" + (item.statusCn == null ? 0 : item.statusCn) + "</td>" + "<td style=\"width:9%;\" class='statisticTableTD'>" + (item.number == null ? 0 : item.number) + "</td>" + "<td style=\"width:9%;\" class='statisticTableTD'>" + (item.source1 == null ? 0 : item.source1) + "</td>" + "<td style=\"width:9%;\" class='statisticTableTD'>" + (item.source0 == null ? 0 : item.source0) + "</td>" + "</tr>"; }); table += "</table>"; return table; } }]
5.實現多層表頭
colspan 每格所占的列數
rowspan 每格所占的行數
columns: [ [{ title: '這是標題', field: '', align: 'center', valign: 'middle', colspan: 10 }], [{ title: '這是標題1', field: '', align: 'center', valign: 'middle', colspan: 1, rowspan: 2 }, { title: '這是標題2', field: '', align: 'center', valign: 'middle', colspan: 4, rowsapn: 1 }, { title: '這是標題3', field: '', align: 'center', valign: 'middle', colspan: 5, rowsapn: 1 }], [{ field: 'title1', //列ID同時也是指定要顯示的數據的ID title: '標題', width: 100, align: 'center', valign: 'middle', sortable: true }, ...... ] ]
下面是遇到的問題:
問題1.在設置為服務器端分頁時,獲取頁碼的params.pageNumber會返回undefined
這是因為queryParamsType的默認參數是limit,在官方說明中這樣解釋:
"如果 queryParamsType = 'limit' ,返回參數必須包含limit, offset, search, sort, order 否則, 需要包含: pageSize, pageNumber, searchText, sortName, sortOrder. 返回false將會終止請求"
有兩種解決方法:
1.為queryParamsType傳空參數,即queryParamsType : "",這時沒有params.limit,但可用params.pageSize來代替
2.修改源碼
首先在bootstrap-table.min.js中搜索 "limit"===this.options.queryParamsType&& (完全復制過去搜索,當然因為版本的原因,一些版本代碼細微處可能不太一樣,但是肯定跟limit有關)找到下面的代碼片段:
"limit"===this.options.queryParamsType&&(i={search:i.searchText,sort:i.sortName,order:i.sortOrder},this.options.pagination&&(i.offset=this.options.pageSize===this.options.formatAllRows()?0:this.options.pageSize*(this.options.pageNumber-1),i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize))
可以看到在this.options.pagination&&后面的括號中有i.offset=...和i.limit=...的代碼,
在i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize后面加上,i.pageNumber=this.options.pageNumber(記得一定要英文逗號分隔)
最終修改后結果如下:
"limit"===this.options.queryParamsType&&(i={search:i.searchText,sort:i.sortName,order:i.sortOrder},this.options.pagination&&(i.offset=this.options.pageSize===this.options.formatAllRows()?0:this.options.pageSize*(this.options.pageNumber-1),i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize, i.pageNumber=this.options.pageNumber))
這樣就可以通過params.pageNumber取到頁碼
問題2:在向表格內寫入自定義元素時在列中使用formatter方法,但在元素中不可直接添加事件,否則無效,只可使用js獲取元素后添加事件.
問題3:在向表格內寫入自定義元素時在列中使用formatter方法,但在元素中添加行數據row時,必須先將json數據轉為字符串才可使用,如:
var rows = JSON.stringify(row);
且在添加元素內時必須使用單引號('')包含,如:
"<span class='classDataTable transRelateName' table-data='" + JSON.stringify(row) + "'>" + row.relateName + "</span>"
問題4:當表格中有點擊事件的自定義元素時,換頁會導致無法點擊?
方法一(推薦,如果在vue等框架內要保證類名和事件函數內調用的函數是唯一的):在寫點擊事件時需要按如下方法書寫:
$(document).on('click', '.researchName', function () {}
方法二:把事件單獨寫一個函數,在表格中添加換頁事件onPageChange,事件調用函數就行
問題5:設置列寬問題
首先要給table加個下面的樣式:
table-layout: fixed;
然后給列設置屬性:
width: 300
