最近被安排到一个新的项目里,首先被分配了一个成果管理的模块,虽然是简单的增删改查,但是也费了不少功夫。

其中耽误最长的时间就是form中嵌套了两个可编辑列表的子表。废话不说上干货 = =

参考资料 1. http://bootstrap-table.wenzhixin.net.cn/documentation/ api

    2. http://blog.csdn.net/lzxadsl/article/details/49181127

//2017.10.17补充相关版本的bootstrap及edit.js

链接: https://pan.baidu.com/s/1gflGSW7 密码: ef5a

20180913 更新链接

链接: https://pan.baidu.com/s/1vPdFzr3XL7QKkGGP5bk_aQ 密码: kq97

界面图:

jsp代码:

简单的一个按钮和一个普通的table

<div class="my_table_bar">
<div class="col-xs-10 bar_title">
<p align="center">
<strong>成果的知识产权情况</strong>
</p>
</div>
<div class="col-xs-2 bar_option">
<a class="insert" href="javascript:addRow(2);" title="新增行">
<i class="glyphicon glyphicon-plus" id="editTable_add_kjcg"></i>
新增
</a>
</div>
</div>
<table id="reportTable2" class="table table-bordered table-hover"></table>

js代码:

/*
* @param 主表ID
* 加载可编辑列表公共方法*/
function loadEditTable(pid){
//重置table内数据
$('#reportTable1').bootstrapTable('destroy');//这里必须要添加这个销毁,否则新增、修改、查看的切换可编辑列表中的数据可能加载出现问题。
$('#reportTable2').bootstrapTable('destroy'); $('#reportTable1').bootstrapTable({
method: 'get',
url:contextPath + '/cggl/getHJQKTable.do?code='+pid,
editable:true,//开启编辑模式
clickToSelect: true,
cache : false,
columns: [
{field:"JX_NAME",title:"所获奖项明称",align:"center",edit:{required:true,type:'text' }},
{field:"JX_ORG",title:"奖励单位",align:"center",edit:{type:'text' }},
{field:"JX_TIME",title:"奖励年度",align:"center",edit:{type:'text' }},
{field:"JX_RANK",title:"授奖等级",align:"center",edit:{type:'text' }},
{field:"operate",title:"操作",align:"center",formatter : operateFormatter1,edit:false}
],
onEditableHidden: function(field, row, $el, reason) { // 当编辑状态被隐藏时触发
if(reason === 'save') {
var $td = $el.closest('tr').children();
$td.eq(-1).html((row.price*row.number).toFixed(2));
$el.closest('tr').next().find('.editable').editable('show'); //编辑状态向下一行移动
} else if(reason === 'nochange') {
$el.closest('tr').next().find('.editable').editable('show');
}
},
onEditableSave: function (field, row, oldValue, $el) {
$table = $('#reportTable1').bootstrapTable({});
$table.bootstrapTable('updateRow', {index: row.rowId, row: row});
}
}); $('#reportTable2').bootstrapTable({
method: 'get',
url:contextPath + '/cggl/getZscqTable.do?code='+pid,
editable:true,//开启编辑模式
clickToSelect: true,
cache : false,
columns: [
{field:"ZSCQ_XS",title:"知识产权形式",align:"center",edit:{required:true ,type:'text'}},
{field:"ZSCQ_NAME",title:"所获知识产权项目名称",align:"center",edit:{type:'text'}},
{field:"ZSCQ_CODE",title:"知识产权号",align:"center",edit:{type:'text'}},
{field:"ZSCQ_TIME",title:"授权时间",align:"center",edit:{type:'text'}},
{field:"operate",title:"操作",align:"center",formatter : operateFormatter2,edit:false}
],
onEditableSave: function (field, row, oldValue, $el) {
$table = $('#reportTable1').bootstrapTable({});
$table.bootstrapTable('updateRow', {index: row.rowId, row: row});
}
}); }

PS:上面提到的destroy方法,如果不加的话,很多时候可编辑列表都是直接调用的缓存中的数据。举个例子,就是我先打开新增,可编辑列表中是没有数据的,再打开修改的话,可编辑列表同样会没有数据,很奇怪,但是具体的原因我也没有找到,ajax 中 cache也已经设置成了false。头大

java代码:

其实我感觉后台是没必要贴的,但是想想我在查阅资料的时候,网上找的资料大多数不全,所以换位思考下,我就全贴出来了。

这里有一个点就是我先把主表保存了,返回了插入数据的ID,然后用这个ID作为外键,将子表数据新增。

其他的话,修改我是先删除ID关联的子表所有数据,然后再新增。(这里如果有更好的方法记得@我,谢谢大神)

    /**
* 新增
* 包括对成果获奖情况和知识产权情况的保存
*/
@SuppressWarnings("rawtypes")
@RequestMapping("/add.do")
public void addToCggl() {
HttpServletRequest request = getRequest();
HttpServletResponse response = getResponse(); try {
// 全路径对象或者表名
String className = request.getParameter(OBJECTID_PARAMETER).trim();
//获取对应的子表数据
String hjqk = request.getParameter("hjqk").trim();
String zscq = request.getParameter("zscq").trim(); // JDBC处理方式
Map entityValue = assembleParameterMap(request.getParameterMap());
entityValue.remove("objectId");
//将子表数据移除
entityValue.remove("hjqk");
entityValue.remove("zscq"); jdbcService.saveCommonObject(className, entityValue);
String parentID = entityValue.get("ID").toString(); //调用子表的保存方法
saveEditTable(parentID,hjqk,zscq); String msg = MsgUtil.getI18NTipMessage(CoreTipDefine.ADDT_0001);
commonResult(response, true, msg);
} catch (Exception e) {
e.printStackTrace();
String msg = MsgUtil.getI18NExpMessage(e);
commonResult(response, false, msg);
}
}

子表传过来的值是json字符串。下面就是在java中对json字符串的转换,因为字段不多,所以也没用Gson。

    List<Map<String, String>> list = new ArrayList<Map<String, String>>();
List<Map<String, String>> list1 = new ArrayList<Map<String, String>>(); // 首先把字符串转成 JSONArray 对象
JSONArray json = JSONArray.fromObject(hjqk);
JSONArray json1 = JSONArray.fromObject(zscq); if (json.size() > 0) {
for (int i = 0; i < json.size(); i++) {
JSONObject job = json.getJSONObject(i); // 遍历 jsonarray
// 数组,把每一个对象转成 json 对象
Map<String, String> map = new HashMap<String, String>(); // 得到 每个对象中的属性值
map.put("CG_ID", code);
map.put("JX_NAME", job.get("JX_NAME").toString());
map.put("JX_ORG", job.get("JX_ORG").toString());
map.put("JX_TIME", job.get("JX_TIME").toString());
map.put("JX_RANK", job.get("JX_RANK").toString());
map.put("id", UUIDGenerator.generateUUID()); list.add(map);
}
}

最后是bootstrap-table-edit.js

/**
* 可编辑表格插件
* 如果编辑表格中有用到,下拉框和日期,必须先引入
* bootstrap-select 和 bootstrap-datetimepicker两个控件
* @author lizx <851697971@qq.com>
* @version 1.0
* @date 2015-10-13
*/ (function($){
'use strict'; $.extend($.fn.bootstrapTable.defaults, {
editable: false
}); var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initBody = BootstrapTable.prototype.initBody,
_onSort = BootstrapTable.prototype.onSort,
_append = BootstrapTable.prototype.append,
_initHeader = BootstrapTable.prototype.initHeader ;
//添加编辑表格默认属性,如何edit设置为false时,表示该列不可编辑
$.extend(true,BootstrapTable.COLUMN_DEFAULTS,{
edit:{
type:'text'//目前只支持 文本:text 下拉:select 日期:date
}
});
BootstrapTable.prototype.init = function () {
_init.apply(this, Array.prototype.slice.apply(arguments));
var that = this;
that.prevEditRow = null;//上一次编辑的行
that.columns = {};//列配置信息
that.insertRowVal = {};//新插入行的默认值
that.enableAppend = true;//允许添加新行
if (that.options.editable) {
var columnObj = this['getColumns']();
$.each(columnObj,function(i,obj){
$.each(obj,function(z,col){
if(!isNaN(col.fieldIndex) && col.fieldIndex >= 0){
if(col.checkbox)col.edit = false;
that.columns['column'+col.fieldIndex] = col;
that.insertRowVal[col.field] = '';
}
});
});
//this.initEdit();
}
};
/*BootstrapTable.prototype.initHeader = function(){
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
this.$container.find('.fixed-table-header').addClass('success');
};*/
BootstrapTable.prototype.initBody = function () {
var that = this; _initBody.apply(this, Array.prototype.slice.apply(arguments));
if (!that.options.editable) return;
this.initEdit(); //如果列是下拉框,则转换值为对应的文本
$.each(that.columns,function(indx,col){
if(col.edit && col.edit.type == 'select'){
col.edit = $.extend({},$.fn.bootstrapSelect.defaults,col.edit);
if(col.edit.data.length > 0){
that.$body.find('>tr').each(function(){
if(that.getData().length < 1)return true;
var rowData = that.data[$(this).data('index')];//当前点击td所在行的数据
var $td = $(this).find('td').eq(col.fieldIndex);
$.each(col.edit.data,function(i,data){
if(data[col.edit.valueField] == rowData[col.field]){
$td.html(data[col.edit.textField]);
}
});
});
}
else if(col.edit.url){
$.ajax({
url:col.edit.url,
type:'post',
data:col.edit.paramsType == 'json' ? JSON.stringify(col.edit.params) : col.edit.params,
dataType:'json',
success: function(jsonLst) {
col.edit.onLoadSuccess.call(this,jsonLst);
that.$body.find('>tr').each(function(){
if(that.getData().length < 1)return true;
var rowData = that.data[$(this).data('index')];//当前点击td所在行的数据
var $td = $(this).find('td').eq(col.fieldIndex);
$.each(jsonLst,function(i,data){
if(data[col.edit.valueField] == rowData[col.field]){
$td.html(data[col.edit.textField]);
}
});
});
col.edit.data = jsonLst;
col.edit.url = null;
},
error: function(xhr, textStatus, errorThrown){
col.edit.onLoadError.call(this);
col.edit.data = [];
col.edit.url = null;
throw col.field+' 列下拉框数据加载失败';
}
});
}
}
});
};
//根据行号删除指定行
BootstrapTable.prototype.removeRow = function (rowNum) {
var that = this;
var len = that.options.data.length;
if (isNaN(rowNum)){
return;
}
if(that.$body.find('.editable-select').data('index') != rowNum){
recover(that);
}
//删除数据
that.options.data.splice(rowNum,1);
if (len === that.options.data.length){
return;
}
var oldClass = {};//保存被标记修改的样式
that.$body.find('>tr').each(function(indx){
if($(this).hasClass('editable-modify')){
if(indx > rowNum){
oldClass[indx-1] = 'editable-modify';
}
else{
oldClass[indx] = 'editable-modify';
}
}
});
//this.prevEditRow = null;
//this.$body.find('>tr').removeClass('editable-select');
that.initBody();
//将标记改变过行的样式从新设置回去
for(var key in oldClass){
that.$body.find('>tr').eq(key).addClass(oldClass[key]);
}
//this.initEdit();
//没有数据时给提示加上样式
if(that.getData().length < 1){
that.$body.find('>tr').addClass('no-records-found');
}
};
BootstrapTable.prototype.append = function (){
var that = this;
//if(!that.enableAppend)return;
var oldClass = {};//保存被标记修改的样式
that.$body.find('>tr').each(function(indx){
if($(this).hasClass('editable-modify') || $(this).hasClass('editable-insert')){
oldClass[indx] = 'editable-modify';
}
});
arguments[0] = $.extend({},that.insertRowVal,arguments[0]);
_append.apply(this,Array.prototype.slice.apply(arguments));
if (that.options.editable){
//that.initEdit();
setTimeout(function (){
//将标记改变过行的样式从新设置回去
for(var key in oldClass){
that.$body.find('>tr').eq(key).addClass(oldClass[key]);
}
that.$body.find('>tr:last').addClass('editable-modify');
that.$body.find('>tr:last').addClass('editable-insert');//双重保险,防止在快速点击添加时,为给新增行设置editable-modify属性
that.$body.find('>tr:last').click();
},60);
} }; BootstrapTable.prototype.onSort = function () {
_onSort.apply(this, Array.prototype.slice.apply(arguments));
var that = this;
if (that.options.editable) {
this.initEdit();
}
};
BootstrapTable.prototype.getData = function () {
return (this.searchText || this.searchCallback) ? this.data : this.options.data;
};
//获取全部的数据
BootstrapTable.prototype.getAllData = function () {
return this.options.data;
}; BootstrapTable.prototype.getColumns = function () {
return this.options.columns;
};
/**
* 获取有被修改过行的值
*/
BootstrapTable.prototype.getModiDatas = function (){
var that = this;
var datas = [];
that.$body.find('.editable-modify').each(function(){
if(that.data[$(this).data('index')]){
datas.push(that.data[$(this).data('index')]);
}
});
return datas;
}; /**
* 获取指定列的和,参数为列下标
*/
BootstrapTable.prototype.getColTotal = function (num){
var retVal = 0;
this.$body.find('>tr').each(function(){
var colNum = 0;
if($(this).hasClass('editable-select')){
colNum = $(this).find('td').eq(num).find('input').val();
}
else{
colNum = $(this).find('td').eq(num).html();
} if(!isNaN(colNum)){//是数字才做想加
retVal += Number(colNum);
}
});
return retVal;
}; /**
* 创建可编辑表格
*/
BootstrapTable.prototype.initEdit = function(){
var that = this,
data = this.getData();
//this.$body.find('> tr').unbind('click').on('click'
//this.$body.delegate('>tr','click'
this.$body.find('> tr').unbind('click').on('click',function(){
var $tr = $(this);
if($tr.hasClass('editable-select') || data.length < 1 || $tr.hasClass('no-records-found')){
return;
}
$tr.removeClass('no-records-found');
recover(that);
that.prevEditRow = $tr;
$tr.addClass('editable-select');//给当前编辑行添加样式,目前样式为空只做标识使用
that.$body.find('> tr').not(this).removeClass('editable-select');
$tr.find('td').closest('td').siblings().html(function(i,html){
initTrClick(that,this);
});
});
//鼠标点击事件
$(document).bind('mousedown',function(event){
var $target = $(event.target);
if(!($target.parents().andSelf().is(that.$body)) && !($target.parents().andSelf().is($('.datetimepicker')))){
setTimeout(function () {
recover(that);
//that.prevEditRow = null;
//that.$body.find('> tr').removeClass('editable-select');
},10);
};
}); }; $.fn.bootstrapTable.methods.push('getColumns',
'getModiDatas','removeRow','getColTotal','getAllData'); /**
* 给tr添加点击事件
*/
function initTrClick(that,_this){
that.enableAppend = true;
var $td = $(_this);
var $tr = $td.parent();
var rowData = that.data[$tr.data('index')];//当前点击td所在行的数据
var tdIndex = $tr.children().index($td);//当前点击的td下标
var tdOpt = that.columns['column'+tdIndex];
if(rowData.IS_TYPING!="0"&&rowData.IS_TYPING!="2"){//判断接口取数方式
if(!tdOpt.edit || typeof tdOpt.edit != 'object'){
return ;
}
$td.data('field',tdOpt.field);
if(!$td.data('oldVal')){
$td.data('oldVal',$.trim(rowData[tdOpt.field]));
}
var height = $td.innerHeight() - 3;
var width = $td.innerWidth() - 2;
$td.data('style',$td.attr('style'));//保存原来的样式
$td.attr('style','margin:0px;padding:1px!important;');
var placeholder = '';
if(tdOpt.edit.required == true){
placeholder = '必填项';
}
var value = rowData[tdOpt.field] == null || rowData[tdOpt.field] == ''?'':rowData[tdOpt.field];
$td.html('<div style="margin:0;padding:0;overflow:hidden;border:solid 0px red;height:'+(height)+'px;width:'+(width)+'px;">'
+'<input type="text" placeholder="'+placeholder+'" value="'+value+'" style="margin-left: 0px; margin-right: 0px; padding-top: 1px; padding-bottom: 1px; width:100%;height:100%">'
+'</div>');
$td.width(width);
var $input = $td.find('input');
if(!tdOpt.edit.type || tdOpt.edit.type == 'text'){
if(tdOpt.edit['click'] && typeof tdOpt.edit['click'] === 'function'){
$input.unbind('click').bind('click',function(event){
tdOpt.edit['click'].call(this,event);
});
}
if(tdOpt.edit['focus'] && typeof tdOpt.edit['focus'] === 'function'){
$input.unbind('focus').bind('focus',function(event){
tdOpt.edit['focus'].call(this,event);
});
}
$input.unbind('blur').on('blur',function(event){
if(tdOpt.edit['blur'] && typeof tdOpt.edit['blur'] === 'function'){
tdOpt.edit['blur'].call(this,event);
}
});
/*$input.unbind('keyup').on('keyup',function(event){
debugger;
var reg=new RegExp("/[^\d{1,}\.\-\d{1,}|\d{1,}]/g");
if(!reg.test($input.val())){
$input.val($input.val().replace(/[^\d{1,}\.\-\d{1,}|\d{1,}]/g, ""));
}
});*/ }
else if(tdOpt.edit.type == 'select'){
$input.bootstrapSelect(tdOpt.edit);
}
else if(tdOpt.edit.type == 'date'){
$td.html('<div style="margin:0;padding:0;overflow:hidden;border:solid 0px red;height:'+(height)+'px;width:'+(width)+'px;" class="input-group date form_datetime" data-link-field="dtp_editable_input">'
+'<input class="form-control" type="text" value="'+value+'">'
+'<span class="input-group-addon"><span class="glyphicon glyphicon-th"></span></span>'
+'</div>'
+'<input type="hidden" id="dtp_editable_input" value="'+value+'"/>'
);
that.$body.find('.form_datetime').datetimepicker({
weekStart: 1,
todayBtn: 1,
autoclose: 1,
todayHighlight: 1,
startView: 2,
forceParse: 0,
language:'zh-CN',
format: 'yyyy-mm-dd hh:ii:ss',
pickerPosition: 'bottom-left',
showMeridian: 1
});
}
}else{
return;
}
}
/**
* 恢复tr,使之处于不可编辑状态
*/
function recover(that){
var isModi = false;//判断行值是否变动过
if(that.prevEditRow != null){
that.prevEditRow.find('td').closest('td').siblings().html(function(i,html){
$(this).attr('style',$(this).data('style'));
var textVal = $(this).find('input[type="text"]').val();
var hiddenVal = $(this).find('input[type="hidden"]').val();
// if(typeof $(this).find('input[type="text"]').bootstrapSelect('getText') != 'object'){
if(typeof $(this).find('input[type="text"]') != 'object'){
$(this).find('input[type="text"]').bootstrapSelect('destroy');
} if(textVal != undefined){
if($(this).data('oldVal') != (hiddenVal?hiddenVal:$.trim(textVal)) && $(this).data('field')) {
that.data[that.prevEditRow.data('index')][$(this).data('field')] = hiddenVal?hiddenVal:$.trim(textVal);
isModi = true;
}
if(that.columns['column'+i].edit.required == true){
if(textVal == null || textVal == ''){
that.enableAppend = false;
return '<span style="color:red;">必填项不能为空</span>';
}
}
return $.trim(textVal);
}
});
//新值跟旧值不匹配证明被改过
if(isModi || that.prevEditRow.hasClass('editable-insert')){
that.prevEditRow.addClass('editable-modify');
}
else{
that.prevEditRow.removeClass('editable-modify');
}
that.prevEditRow = null;
that.$body.find('> tr').removeClass('editable-select');
}
} })(jQuery);

2017/08/03

对新增,删除调用方法的补充

function operateFormatter1(value, row, index) {
return [
"<a class=\"remove\" href='javascript:removeRow("+index+",1)' title=\"删除改行\">",
"<i class='glyphicon glyphicon-remove'></i>",
"</a> "
].join('');
}
function operateFormatter2(value, row, index) {
return [
"<a class=\"remove\" href='javascript:removeRow("+index+",2)' title=\"删除改行\">",
"<i class='glyphicon glyphicon-remove'></i>",
"</a> "
].join('');
} $('#reportTable1','#reportTable2').on( 'click', 'td:has(.editable)', function (e) {
//e.preventDefault();
e.stopPropagation(); // 阻止事件的冒泡行为
$(this).find('.editable').editable('show'); // 打开被点击单元格的编辑状态
} ); //可编辑列表新增一行
function addRow(mark){
var rows = []; //通过mark来判断为哪个可编辑框创建新一行
if(mark == 1){
$('#reportTable1').bootstrapTable('append',rows);
}else if(mark == 2){
$('#reportTable2').bootstrapTable('append',rows);
} }
//删除指定行
function removeRow(deleteIndex,mark){
if(mark == "1"){
$('#reportTable1').bootstrapTable('removeRow', deleteIndex);
}else if(mark == "2"){
$('#reportTable2').bootstrapTable('removeRow', deleteIndex);
}
}

好了,基本就是这些。

最新文章

  1. Oculus中OVRPlayerController飞行视角的制作
  2. IE兼容问题,各类css hack代码(亲测有效)
  3. Cornerstone 哪些错误
  4. 边工作边刷题:70天一遍leetcode: day 80
  5. hdu----(4521)小明系列问题——小明序列
  6. VS2015试验随手记
  7. 在线协作沟通工具DesignBoard帮助设计团队更有效地进行沟通与版本管理
  8. Disharmony Trees 树状数组
  9. java.lang.Class类中的某些方法
  10. 「Algospot」量化QUANTIZE
  11. 字符串、数组、对象常用API
  12. JSJ—案例谈面向对象
  13. springmvc简单集成shiro
  14. 全文搜索引擎 Elasticsearch 入门
  15. tomcat下部署应用helloworld
  16. SQL数据同步之发布订阅
  17. HDU 2049 不容易系列之(4)——考新郎 (错排+组合)
  18. IDEA启动时自动报Plugin Error错误
  19. 使用OleDB组件连接和访问Oracle数据库
  20. 跟着百度学PHP[10]-读取COOKIE案例

热门文章

  1. error C4996: &#39;swprintf&#39;: swprintf has been changed to conform with the ISO C standard,set _CRT_NON_CONFORMING_SWPRINT
  2. TCP/IP笔记(五)IP协议相关技术
  3. 细说OC中的load和initialize方法
  4. Ecplise 中 加载JDBC 连接 Mysql 数据库读取数据
  5. APICloud框架—db数据库模块
  6. AFNetworking 内部详解
  7. Mac IDEA插件——protobuf 插件
  8. phpcms基础
  9. 单Js 的重力游戏开发
  10. 【代码学习】MYSQL数据库的常见操作