使用bootstrapTable實現數據左右移動的功能其實做過很多了,但原來實現的功能都是比較單一,都是選中單條數據進行移動。這次需要實現的功能比較全面,中間遇到不少的坑,此次正好在這里將所有的功能代碼梳理一下。
實現以下功能:
1.選中單條數據進行左右移動
2.將列表中所有數據全部進行左右移動
3.左邊的數據移動到右邊后,為其增加一個序號列,並根據右側列表的數據自動遞增序號
4.右側列表中的數據可以隨意拖動排序,序號自動變更
5.在列表上的搜索框輸入關鍵字,定位到列表中對應的數據並選中
html代碼:

1 <div class="movebox clearfix box-padding10"> 2 <div class="movebox-left fl"> 3 <p>可選考核項目</p> 4 <div class="form-inline form-inline-auto" style="padding-right: 0;"> 5 <div class="form-group t-right10"> 6 <select class="form-control" style="min-width: 110px" id="kaoheFW" name="kaoheFW"> 7 <option value="2">專科</option> 8 <option value="1">公共</option> 9 </select> 10 </div> 11 <div class="form-control-radio" style="width: auto; min-width: 0;"> 12 <input type="radio" class="radio" name="leixing" value="" checked> 13 <label class="f-left t-right10 t-lineheight28">全部</label> 14 <input type="radio" class="radio" name="leixing" value="2"> 15 <label class="f-left t-right10 t-lineheight28">操作</label> 16 <input type="radio" class="radio" name="leixing" value="1"> 17 <label class="f-left t-right10 t-lineheight28">理論</label> 18 </div> 19 <div class="form-group"> 20 <input class="form-control" placeholder="請輸入考核項目" type="text" value="" id="kaoheXM"> 21 </div> 22 </div> 23 <div class="clear"></div> 24 <div class="form-table-height main-y-scroll" id="kaoheXMList"> 25 <table class="table table-striped table-bordered table-hover text-center" id="tableleft"> 26 <thead> 27 28 </thead> 29 <tbody></tbody> 30 </table> 31 </div> 32 <div class="space"></div> 33 </div> 34 <div class="movebox-btn fl"> 35 <span id="add_all" class="icon iconfont icon-youshuangjiantou"></span> 36 <span id="add" class="icon iconfont icon-jiantou-you" onclick="add_keShiKHXM()"></span> 37 <span id="remove" class="icon iconfont icon-jiantou-zuo" onclick="remove_keShiKHXM()"></span> 38 <span id="remove_all" class="icon iconfont icon-zuoshuangjiantou"></span> 39 </div> 40 <div class="movebox-right fl"> 41 <p>已選擇考核項目</p> 42 <div class="form-inline form-inline-auto" style="padding-right: 0;"> 43 <div class="form-group t-right10"> 44 <select class="form-control" style="min-width: 110px" id="keshiKHFW" name="keshiKHFW"> 45 <option value="2">專科</option> 46 <option value="1">公共</option> 47 </select> 48 </div> 49 <div class="form-control-radio" style="width: auto; min-width: 0;"> 50 <input type="radio" class="radio" name="keshiLX" value="" checked> 51 <label class="f-left t-right10 t-lineheight28">全部</label> 52 <input type="radio" class="radio" name="keshiLX" value="2"> 53 <label class="f-left t-right10 t-lineheight28">操作</label> 54 <input type="radio" class="radio" name="keshiLX" value="1"> 55 <label class="f-left t-right10 t-lineheight28">理論</label> 56 </div> 57 <div class="form-group" > 58 <input class="form-control" placeholder="請輸入考核項目" type="text" value="" id="keshiKHXM" > 59 </div> 60 </div> 61 <div class="clear"></div> 62 <div class="form-table-height main-y-scroll" id="keshiKHXMList"> 63 <table class="table table-striped table-bordered table-hover text-center" id="tableright"> 64 <thead> 65 66 </thead> 67 <tbody> 68 </tbody> 69 </table> 70 </div> 71 <p class="t-gray">說明:拖拽行進行排序</p> 72 </div> 73 </div>
初始化bootstraptable:

1 function Init_kaoHeXM() { 2 3 //獲取關鍵字 4 var kaoHeFW = $('#kaoheFW option:selected').val();; 5 var kaoHeLX = $('input[name="leixing"]:checked').val(); 6 7 $('#tableleft').bootstrapTable("destroy"); 8 //初始化table 9 $('#tableleft').bootstrapTable({ 10 url: "/HLGL/ChengJiGL/GetkaoheXMList", 11 postData: function () { 12 return { "keShiID": keShiID, "kaoHeFW": kaoHeFW, "kaoHeLX": kaoHeLX } 13 }, 14 columns: [ 15 { field: 'KAOHEXMID', title: "考核項目ID", visible: true }, 16 { field: 'XIANGMUMC', title: "項目名稱", visible: true }, 17 { field: 'KAOHELX', title: "考核類型", visible: true, formatterType: 'JSON', formatter: { '1': '理論', '2': '操作' } } 18 19 ], 20 pagination: false, 21 autoSelectFirstRow: false, 22 //height: $(window).height() - 117 23 }); 24 } 25 function Init_keShiKHXM() { 26 //獲取關鍵字 27 var kaoHeFW = $('#keshiKHFW option:selected').val();; 28 var kaoHeLX = $('input[name="keshiLX"]:checked').val(); 29 30 $('#tableright').bootstrapTable("destroy"); 31 $('#tableright').bootstrapTable({ 32 url: "/HLGL/ChengJiGL/GetkeshiKHXMList", 33 postData: function () { 34 return { "keShiID": keShiID, "kaoHeFW": kaoHeFW, "kaoHeLX": kaoHeLX } 35 }, 36 columns: [ 37 { field: 'PAIXUXH', title: "排序序號", width: "5%", visible: true, class: "index", }, 38 { field: 'KESHIKHXMID', title: "科室考核項目ID", visible: false }, 39 { field: 'KAOHEXMID', title: "考核項目ID", visible: true }, 40 { field: 'XIANGMUMC', title: "項目名稱", visible: true }, 41 { field: 'KAOHELX', title: "考核類型", visible: true, formatterType: 'JSON', formatter: { '1': '理論', '2': '操作' } } 42 43 ], 44 pagination: false,//不分頁 45 autoSelectFirstRow: false//默認不選中第一行 46 //height: $(window).height() - 117 47 }) 48 }
初始化后定義了兩個變量存放bootstrapTable:
$tableLeft = $('#tableleft').bootstrapTable();
$tableRight = $('#tableright').bootstrapTable();
下面就開始實現第一個功能:選中單條數據進行左右移動 ,右移時增加序號列並在原有基礎上遞增
這個功能比較簡單,沒有什么需要注意的地方
1 //添加科室考核項目 2 function add_keShiKHXM() { 3 //注意getSelectedRow這個是內部重新封裝的方法,原生獲取選中行應該是$("#tableleft").bootstrapTable('getSelections'); 4 var selectContent = $tableLeft.bootstrapTable('getSelectedRow'); 5 if (selectContent == "" || selectContent==null || selectContent == undefined) { 6 HRP.AlertError("請先選擇需要操作的數據!"); 7 return false; 8 } 9 selectContent.KESHIID = keShiID; 10 11 //獲取到右側列表的排序序號,給左側選中行進行設置 12 var len = $('#tableright tr .index').length; 13 if (len == 1) 14 { selectContent.PAIXUXH = 1; } 15 else { 16 selectContent.PAIXUXH = parseInt($('#tableright tr').eq(len - 1).children(0).eq(0)[0].innerText) + 1;//len-1 是因為有標題列 17 } 18 19 20 $tableRight.bootstrapTable("append", selectContent); 21 var selects = $tableLeft.bootstrapTable('getSelectedRow'); 22 23 var KAOHEXMID = selects.KAOHEXMID; 24 25 $tableLeft.bootstrapTable('remove', { 26 field: 'KAOHEXMID', 27 values: [String(KAOHEXMID)] 28 }); 29 30 } 31 32 //移除科室考核項目 33 function remove_keShiKHXM() { 34 //注意getSelectedRow這個是內部重新封裝的方法,原生獲取選中行應該是$("#tableright").bootstrapTable('getSelections'); 35 var selectContent = $tableRight.bootstrapTable('getSelectedRow'); 36 if (selectContent == "" || selectContent==null || selectContent == undefined) { 37 HRP.AlertError("請先選擇需要操作的數據!"); 38 return false; 39 } 40 41 42 $tableLeft.bootstrapTable("append", selectContent); 43 var selects = $tableRight.bootstrapTable('getSelectedRow'); 44 45 var daima = selects.KAOHEXMID; 46 $tableRight.bootstrapTable('remove', { 47 field: 'KAOHEXMID', 48 values: [String(daima)] 49 }); 50 };
第二個功能:將列表所有數據進行左右移動
1 $("#add_all").click(function () { 2 3 if ($("#tableleft tbody tr.no-records-found").length > 0) { 4 HRP.AlertError("當前沒有可以操作的數據!"); 5 return false; 6 } 7 $("#tableright tbody tr.no-records-found").remove();//這一句是刪除掉表格中沒有數據時的提示行 8 // $("#tableright").find(".no-records-found").remove();· 9 var len = 0; 10 if ($("#tableright tbody tr").length == 0) { 11 len = 1; 12 } 13 else { 14 len = parseInt($("#tableright tbody tr:last-child .index").html()) + 1; 15 } 16 17 //下面兩個for循環不能合在一起,因為delete以后eq(i)獲取的數據會隨着改變,不是原來索引的數據 18 for (var i = 0; i < $("#tableleft tbody tr").length; i++) { 19 var content = {"PAIXUXH":len,"KAOHEXMID":$("#tableleft tbody tr").eq(i).find("td")[0].innerText,"XIANGMUMC":$("#tableleft tbody tr").eq(i).find("td")[1].innerText,"KAOHELX":$("#tableleft tbody tr").eq(i).find("td")[2].innerText} 20 $tableRight.bootstrapTable("append", content); 21 len++; 22 } 23 24 //$("#tableleft tbody tr").remove(); 25 //這里不能用remove,此時需要用bootstrapTable自帶的刪除,否則下次對表進行操作時remove的數據會再次出現 26 // 27 28 var xiangMuLength = $("#tableleft tbody tr").length; 29 for (var j = 0; j < xiangMuLength; j++) { 30 var index = $("#tableleft tbody tr").eq(0).attr("data-index"); 31 $tableLeft.bootstrapTable('deleteRow',index.toNumber()); 32 } 33 }); 34 35 $("#remove_all").click(function () { 36 if ($("#tableright tbody tr.no-records-found").length > 0) { 37 HRP.AlertError("當前沒有可以操作的數據!"); 38 return false; 39 } 40 $("#tableleft tbody tr.no-records-found").remove(); 41 $("#tableright tbody td.index").remove(); 42 43 44 //下面兩個for循環不能合在一起,因為delete以后eq(i)獲取的數據會隨着改變,不是原來索引的數據 45 for (var i = 0; i < $("#tableright tbody tr").length; i++) { 46 47 var content = {}; 48 content = {"KAOHEXMID":$("#tableright tbody tr").eq(i).find("td")[0].innerText,"XIANGMUMC":$("#tableright tbody tr").eq(i).find("td")[1].innerText,"KAOHELX":$("#tableright tbody tr").eq(i).find("td")[2].innerText} 49 $tableLeft.bootstrapTable("append", content); 50 } 51 52 var keShiXMLength = $("#tableright tbody tr").length; 53 for (var j = 0; j < keShiXMLength; j++) { 54 55 var index = $("#tableright tbody tr").eq(0).attr("data-index"); 56 $tableRight.bootstrapTable('deleteRow',index.toNumber()); 57 } 58 59 60 });
這里全部數據的左右移動我用的是遍歷再使用bootstrapTable的append方法來進行插入,原本我是直接使用的html的appendto方法來進行實現,結果發現存在嚴重的bug。
通過這種方式雖然在表面上是實現功能了,可以將數據移過去進行保存,但是如果先點擊移動全部的按鈕將數據轉移后,再選中一條數據進行移動,會出現原本列表中被轉移的數據會再次出現。經調試發現這種方式雖然被轉移了,但數據所屬的列表還是原列表,但具體的原理不太清楚。所以后來我通過遍歷拼接json字符串最后通過bootstrapTable的append方法進行實現。這樣沒有出現上面的問題。
下面是我原來的有bug的代碼,以后當做反面事例:
$("#add_all").click(function () { if ($("#tableleft tbody tr.no-records-found").length > 0) { HRP.AlertError("當前沒有可以操作的數據!"); return false; } $("#tableright tbody tr.no-records-found").remove(); // $("#tableright").find(".no-records-found").remove(); var len = 0; if ($("#tableright tbody tr").length == 0) { len = 1; } else { len = parseInt($("#tableright tbody tr:last-child .index").html()) + 1; } for (var i = 0; i < $("#tableleft tbody tr").length; i++) { var tdNo = "<td class='index'>" + len + "</td>"; $("#tableleft tbody tr").eq(i).prepend(tdNo); len++; } $("#tableleft tbody tr").appendTo($("#tableright tbody")).siblings().removeClass("td-active"); }); $("#remove_all").click(function () { if ($("#tableright tbody tr.no-records-found").length > 0) { HRP.AlertError("當前沒有可以操作的數據!"); return false; } $("#tableleft tbody tr.no-records-found").remove(); $("#tableright tbody td.index").remove(); //$("#tableright tbody td:last-child").remove(); $("#tableright tbody tr").appendTo($("#tableleft tbody")).siblings().removeClass("td-active"); });
第三個功能:右側列表實現拖拽排序
//拖拽排序 var fixHelperModified = function (e, tr) { var $originals = tr.children(); var $helper = tr.clone(); $helper.children().each(function (index) { $(this).width($originals.eq(index).width()) }); return $helper; }, updateIndex = function (e, ui) { $('td.index', ui.item.parent()).each(function (i) { $(this).html(i + 1); }); }; $("#tableright tbody").sortable({ helper: fixHelperModified, stop: updateIndex }).disableSelection();
第四個功能:模糊查詢定位數據位置
function dinwei_keShiKHXM() { // 獲取搜索框的值 var kwds = $("#keshiKHXM").val(); // 獲取第一個列表內容 var this_one = {}; var real_name = ''; // 定義數據列表 var list = $("#tableright tr"); // 定義查找的起始值 var true_one = 0; for (var i = 1; i < list.length; i++) { this_one = $(list[i]); real_name = this_one.text().toString(); // 執行like匹配 if(real_name.match(kwds)){ // 處理第當前的結果 if(true_one == active){ // 獲取第一個坐標 var y_len = this_one.offset().top; // 驅動滾動條滾動到指定的位置 $('#keshiKHXMList').mCustomScrollbar('scrollTo', y_len); // 標記當前選中的結果 this_one.addClass('td-active'); this_one.removeClass('on'); }else{ // 標記符合的結果 this_one.addClass('on'); this_one.removeClass('td-active'); } // 累加真實的選擇 true_one++; }else{ this_one.removeClass('on'); this_one.removeClass('td-active'); } } // 判斷是否搜索完畢 如果搜索完畢 則從第一個開始 否則繼續搜索下一個 active = active >= true_one-1 ? 0 : active+1; return false; } function dinwei_kaoHeXM() { // 獲取搜索框的值 var kwds = $("#kaoheXM").val(); // 獲取第一個列表內容 var this_one = {}; var real_name = ''; // 定義數據列表 var list = $("#tableleft tr"); // 定義查找的起始值 var true_one = 0; for (var i = 1; i < list.length; i++) { this_one = $(list[i]); real_name = this_one.text().toString(); // 執行like匹配 if(real_name.match(kwds)){ // 處理第當前的結果 if(true_one == active){ // 獲取第一個坐標 var y_len = this_one.offset().top; // 驅動滾動條滾動到指定的位置 $('#kaoheXMList').mCustomScrollbar('scrollTo', y_len); // 標記當前選中的結果 this_one.addClass('td-active'); this_one.removeClass('on'); }else{ // 標記符合的結果 this_one.addClass('on'); this_one.removeClass('td-active'); } // 累加真實的選擇 true_one++; }else{ this_one.removeClass('on'); this_one.removeClass('td-active'); } } // 判斷是否搜索完畢 如果搜索完畢 則從第一個開始 否則繼續搜索下一個 active = active >= true_one-1 ? 0 : active+1; return false; }
最后就是保存數據了,我因為后台業務原因,只是獲取了列表中的主鍵進行拼接,然后傳遞到后台進行處理
function Save() { if ($('#tableright').bootstrapTable().find("tbody td.index").length > 0) { var data = null; var tableTRs = $('#tableright').bootstrapTable().find("tbody tr"); if (tableTRs != null && tableTRs != undefined) { for (var i = 0; i < tableTRs.length; i++) { var kaoHeXMID = tableTRs.eq(i).find("td").eq(1).text(); if (i == 0) { data = kaoHeXMID; } else { data += "," + kaoHeXMID; } } } } else { HRP.AlertError("請先選擇操作數據,再進行保存!"); return false; } var kaoHeFW = $('#keshiKHFW option:selected').val(); var kaoHeLX = $('input[name="keshiLX"]:checked').val(); postUrl("/HLGL/ChengJiGL/SavekeshiKHXM", { data: data, keShiID: keShiID, kaoHeFW: kaoHeFW,kaoHeLX: kaoHeLX }, function (res) { if (res == true) { HRP.Tip.success("操作成功!"); getParentWindow().doSearch(); closeWin(); } else { HRP.AlertError("操作失敗!"); } }) }