JS组件Bootstrap Table表格行拖拽效果实现代码

前端之家收集整理的这篇文章主要介绍了JS组件Bootstrap Table表格行拖拽效果实现代码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、业务需求及实现效果

项目涉及到订单模块,那天突然接到一个需求,说是两种不同状态的订单之间要实现插单的效果页面上呈现方式是:左右两个Table,左边Table里面是状态为1的订单,右边Table里面是状态为2订单,左边Table里面的行数据拖动到右边Table里面指定行的位置,拖动完成后,左边表格减少一行,右边表格增加一行。除此之外,还需要撤销操作(相当于Ctrl + Z操作),能够返回到上一步的状态。可能描述会让大家模拟两可,反正已经实现了,先来看看效果图吧。

1、先看看拖动之前的效果

2、这是拖动左边表格行数据的效果

3、拖动一行完成之后表格数据的效果

4、第二次、第三次拖动完成后效果

5、右边表格上面撤销操作点击效果

6、多次点击撤销,表格回到初始状态

二、代码示例

接到需求的第一感觉是应该上Bootstrap table api里面找一下,毕竟开源的力量是强大的,或许有相关的示例呢。经过一番查找,很可惜,Bootstrap Table没有这种两张表格之间的操作。想想其实也可以理解,Bootstrap Table是针对某个动态表格数据绑定的,它的侧重点是表格内部的功能,比如表格内部行的拖拽排序(Reorder Rows)有很好的解决方案,对于像博主这样的特殊需求,似乎也应该自己去实现。 1、需求分析 既然决定自己去写,开始分析需求,似乎这个操作里面比较困难的是拖拽效果,说到拖拽效果,原来使用JsPlumb的时候那使用太多了,于是就想到了我们神奇的JQuery UI里面的draggable.js 和droppable.js。拖拽的问题解决了,那么还有一个难点,就是撤销操作怎么办?我们知道Ctrl+z的意思是还原,什么叫还原?就是返回到上一步的操作,那么前提是要能够保存上一步的状态,说到保存某一步的状态,博主就知道怎么做了,需要一个全局变量Json,里面要有三个键值对,分别是当前步骤的索引、左边表格的数据、右边表格的数据。似乎也不太难嘛,就此着手,开干。 2、代码示例 2.1 cshtml页面代码

@ViewBag.Title @Styles.Render("~/Content/css") @Styles.Render("~/Content/table-css") @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/knockout") @Scripts.Render("~/bundles/bootstrap") @Scripts.Render("~/bundles/bootstrap-table") @RenderSection("Scripts",false) @RenderBody()

@{
ViewBag.Title = "订单插单";
Layout = "~/Views/Shared/_Layout.cshtml";
}

@Scripts.Render("~/bundles/Order/InsertOrder")
@Styles.Render("~/bundles/Order/css")
@Scripts.Render("~/Content/bootstrap/datepicker/js")
@Styles.Render("~/Content/bootstrap/datepicker/css")

<script src="~/Content/jquery-ui-1.11.4.custom/jquery-ui.min.js">

<div class="panel-body" style="padding-bottom:0px;">

<div class="panel panel-default" style="margin-bottom:0px;">
<div class="panel-heading">查询条件


<div class="panel-body container-fluid">
<div class="row">
<div class="col-md-3">
<label for="txt_search_ordernumber" class="col-sm-4 control-label" style="margin-top:6px;">订单号
<span class="col-sm-8">
<input type="text" class="form-control" id="txt_search_ordernumber">

<div class="row" style="margin-top:15px;">
<div class="col-md-3">
<label for="txt_search_carcode" class="col-sm-4 control-label" style="margin-top:6px;">整车编码
<span class="col-sm-8">
<input type="text" class="form-control" id="txt_search_carcode">

<div class="row" style="float:right;margin-right:50px;margin-top:13px;">

<div class="collapse_div_outside">
<div class="collapse_div_inside">
<span id="span_collapse" href="#div_more_search" class="collapse_div_inside_ele">展开<label class="glyphicon glyphicon-menu-down">

@*<div id="toolbar_left" class="btn-group">

*@
撤销

2.2 js代码

var m_oTable = null;

$(function () {
//1.初始化表格
m_oTable = new TableInit();
m_oTable.Init();

//2.初始化按钮事件
var oButtonInit = new ButtonInit();
oButtonInit.Init();

//3.日期控件的初始化
$(".datetimepicker").datetimepicker({
format: 'yyyy-mm-dd hh:ii',autoclose: true,todayBtn: true,});

});

//表格相关事件和方法
var TableInit = function () {
var oTableInit = new Object();

oTableInit.Init = function () {
     //初始化左边表格
$('#tb_order_left').bootstrapTable({
url: '/api/OrderApi/get',method: 'get',striped: true,cache: false,pagination: true,height: 600,uniqueId:"TO_ORDER_ID",queryParams: oTableInit.queryParams,queryParamsType: "limit",sidePagination: "server",pageSize: 10,pageList: [10,25,50,100],search: true,strictSearch: true,showColumns: true,showRefresh: true,minimumCountColumns: 2,clickToSelect: true,columns: [{
checkBox: true
},{
field: 'ORDER_NO',title: '订单号'
},{
field: 'BODY_NO',title: '车身号'
},{
field: 'VIN',title: 'VIN码'
},{
field: 'TM_MODEL_MATERIAL_ID',title: '整车编码'
},{
field: 'ORDER_TYPE',title: '订单类型'
},{
field: 'ORDER_STATUS',title: '订单状态'
},{
field: 'CREATE_DATE',title: '订单导入时间'
},{
field: 'PLAN_DATE',title: '订单计划上线日期'
},{
field: 'VMS_NO',title: 'VMS号'
},{
field: 'ENGIN_CODE',title: '发动机号'
},{
field: 'TRANS_CODE',title: '变速箱号'
},{
field: 'OFFLINE_DATE_ACT',title: '实际下线日期'
},{
field: 'HOLD_RES',title: 'hold理由'
},{
field: 'SPC_FLAG',title: '特殊标记'
},],onLoadSuccess: function (data) {
//表格加载完成之后初始化拖拽
          oTableInit.InitDrag();
}
});
     //初始化右边表格
$('#tb_order_right').bootstrapTable({
url: '/api/OrderApi/get',toolbar: '#toolbar_right',queryParams: oTableInit.queryParamsRight,//ajaxOptions: { departmentname: "",statu: "" },columns: [
{
field: 'ORDER_NO',onLoadSuccess: function (data) {
oTableInit.InitDrop();
}
});
};
//注册表格行的draggable事件
oTableInit.InitDrag = function () {
$('#tb_order_left tr').draggable({
helper: "clone",start: function (event,ui) {
var old_left_data = JSON.stringify($('#tb_order_left').bootstrapTable("getData"));
var old_right_data = JSON.stringify($('#tb_order_right').bootstrapTable("getData"));
var odata = { index: ++i_statuindex,left_data: old_left_data,right_data: old_right_data };
arrdata.push(odata);
},stop: function (event,ui) {

}
});
};
//注册右边表格的droppable事件
oTableInit.InitDrop = function () {
$("#tb_order_right").droppable({
drop: function (event,ui) {
var arrtd = $(ui.helper[0]).find("td");
var rowdata = {
ORDER_NO: $(arrtd[1]).text(),BODY_NO: $(arrtd[2]).text(),VIN: $(arrtd[3]).text(),TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(),ORDER_TYPE: $(arrtd[5]).text(),ORDER_STATUS: $(arrtd[6]).text(),CREATE_DATE: $(arrtd[7]).text() == "-" ? null : $(arrtd[7]).text(),PLAN_DATE: $(arrtd[8]).text() == "-" ? null : $(arrtd[8]).text(),VMS_NO: $(arrtd[9]).text(),ENGIN_CODE: $(arrtd[10]).text(),TRANS_CODE: $(arrtd[11]).text(),OFFLINE_DATE_ACT: $(arrtd[12]).text() == "-" ? null : $(arrtd[12]).text(),HOLD_RES: $(arrtd[13]).text(),SPC_FLAG: $(arrtd[14]).text(),TO_ORDER_ID: $(ui.helper[0]).attr("data-uniqueid")

};
var oTop = ui.helper[0].offsetTop;
var iRowHeadHeight = 40;
var iRowHeight = 37;
var rowIndex = 0;
if (oTop <= iRowHeadHeight + iRowHeight / 2) {
rowIndex = 0;
}
else {
rowIndex = Math.ceil((oTop - iRowHeadHeight) / iRowHeight);
}
          //插入右边表格指定位置行数据
$("#tb_order_right").bootstrapTable("insertRow",{ index: rowIndex,row: rowdata });
$('#tb_order_left').bootstrapTable("removeByUniqueId",$(ui.helper[0]).attr("data-uniqueid"));
oTableInit.InitDrag();
}
});
};

oTableInit.queryParams = function (params) { //配置参数
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit,//页面大小
offset: params.offset,//页码
strBodyno: $("#txt_search_bodynumber").val(),strVin: $("#txt_search_vinnumber").val(),strOrderno: $("#txt_search_ordernumber").val(),strEngincode: $("#txt_search_engin_code").val(),strOrderstatus: 0,strTranscode: $("#txt_search_trans_code").val(),strVms: $("#txt_search_vms").val(),strCarcode: $("#txt_search_carcode").val(),strImportStartdate: $("#txt_search_import_startdate").val(),strImportEnddate: $("#txt_search_import_enddate").val(),strSendStartdate: $("#txt_search_send_startdate").val(),strSendEnddate: $("#txt_search_send_enddate").val(),};
return temp;
};

oTableInit.queryParamsRight = function (params) { //配置参数
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit,//页码
strBodyno: "",strVin: "",strOrderno: "",strEngincode: "",strOrderstatus: 5,strTranscode: "",strVms: "",strCarcode: "",strImportStartdate: "",strImportEnddate: "",strSendStartdate: "",strSendEnddate: "",};
return temp;
};

return oTableInit;
};

//页面按钮初始化事件
var ButtonInit = function () {
var oInit = new Object();
var postdata = {};

oInit.Init = function () {

//查询点击事件
$("#btn_query").click(function () {
$("#tb_order_left").bootstrapTable('refresh');
});

//重置点击事件
$("#btn_reset").click(function () {
$(".container-fluid").find(".form-control").val("");
$("#tb_order_left").bootstrapTable('refresh');
});
//撤销操作点击事件
$("#btn_cancel").click(function () {
if (i_statuindex <= 0) {
return;
}
for (var i = 0; i < arrdata.length; i++) {
if (arrdata[i].index != i_statuindex) {
continue;
}
var arr_left_data = eval(arrdata[i].left_data);
var arr_right_data = eval(arrdata[i].right_data);

$('#tb_order_left').bootstrapTable('removeAll');
$('#tb_order_right').bootstrapTable('removeAll');
$('#tb_order_left').bootstrapTable('append',arr_left_data);
for (var x = 0; x < arr_right_data.length; x++) {
$("#tb_order_right").bootstrapTable("insertRow",{ index: x,row: arr_right_data[x] });
}

//$('#tb_order_right').bootstrapTable('append',arr_right_data);//append之后不能drop
break;
}
i_statuindex--;

//重新注册可拖拽
m_oTable.InitDrag();
//m_oTable.InitDrop();
});

//搜索栏展开收起点击事件
$("#span_collapse").click(function () {
if ($(this).text() == "收起") {
$(this).html('展开<label class="glyphicon glyphicon-menu-down">');
$("#div_more_search").collapse('hide');
}
else {
$(this).html('收起<label class="glyphicon glyphicon-menu-up">');
$("#div_more_search").collapse('show')
}
});
};

return oInit;
};

我们重点来看几个地方的代码2.2.1 左边表格加载成功之后执行表格行的可拖拽。

在draggable的start事件中,我们将拖拽之前的左右表格中的数据全部保存到arrdata变量中,i_statuindex这个全局变量用于记录当前这一步的索引,用于撤销操作。

2.2.2 右边表格在加载成功之后注册表格的droppable事件

    

};
var oTop = ui.helper[0].offsetTop;
var iRowHeadHeight = 40;
var iRowHeight = 37;
var rowIndex = 0;
if (oTop <= iRowHeadHeight + iRowHeight / 2) {
rowIndex = 0;
}
else {
rowIndex = Math.ceil((oTop - iRowHeadHeight) / iRowHeight);
}
$("#tb_order_right").bootstrapTable("insertRow",$(ui.helper[0]).attr("data-uniqueid"));
oTableInit.InitDrag();
}
});

在drop事件时,取到当前拖过来的行数据,计算当前鼠标所在的位置,在右边表格指定位置插入拖过来的行数据。然后删除左边表格拖过来的行数据。

2.2.3 撤销操作代码  

 

$('#tb_order_left').bootstrapTable('removeAll');
$('#tb_order_right').bootstrapTable('removeAll');
$('#tb_order_left').bootstrapTable('append',arr_left_data);
for (var x = 0; x < arr_right_data.length; x++) {
$("#tb_order_right").bootstrapTable("insertRow",row: arr_right_data[x] });
}
//$('#tb_order_right').bootstrapTable('append',arr_right_data);//append之后不能drop
break;
}
i_statuindex--;

//重写注册可拖拽
m_oTable.InitDrag();
});

撤销操作主要是通过全局变量arrdata里面的索引判断撤销到哪一步,然后根据索引取出当前步骤的左右表格数据,依次向两表格插入数据,然后i_statuindex依次递减,直至等于零,由于左边表格行数据全部重写加载过,所以需要重新注册可拖拽事件。就是这么简单的三步就能实现想要的效果,是不是很简单~~

如果大家还想深入学习,可以点击进行学习,再为大家附两个精彩的专题:

以上就是本文的全部内容,希望对大家的学习有所帮助。

原文链接:https://www.f2er.com/bootstrap/51243.html
bootstrapbootstraptabletabletabletable

猜你在找的Bootstrap相关文章