http://www.tuicool.com/articles/YbEVv2v

为什么调用 bootstraptable 原生方法会有问题

首先我必须肯定, bootstraptable 是一款很强大的基于 bootstrap 的插件,下载它的 源码 后,你可以学到很多,开源真的很好。好了,我们回到怎么动态添加可编辑行的问题上,你可以在它的 说明文档 上很容易就找到动态增加行的方法, 于是我们欢欣鼓舞的去使用了,效果很好, 但当我们填好这一行的内容后,再加一行的时候,坑爹的事情发生了,第二个新增可编辑行把第一个给还原了,即变成最初新增编辑行的初始状态,一开始百思不得其解,后来打开源码一看(开源就是好啊),发现是这里的问题

BootstrapTable.prototype.insertRow = function (params) {
if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) {
return;
}
this.data.splice(params.index, 0, params.row);
// 调用 initSearch() 重新把 this.options.data 数据初始化了
this.initSearch();
this.initPagination();
this.initSort();
this.initBody(true);
};

this.initSearch() 重新把 this.options.data 数据初始化了,因为我们是在动态编辑行的文本框里填写的内容,这个内容并没有同步到 this.options.data 里,所以调用 this.initSearch(); 这个方法后,被还原也是板上钉钉的事了。既然我们知道了原因,那就开动脑筋去实践解决方案。

怎么解决

我选择的方法是从根上解决,在填写动态增加可编辑行的文本或下拉内容时加上 onchange 事件,将填好的内容,同步更新到 this.options.data 里,这样下次新增可编辑行的时候就不会还原成初始状态了。下面我附上源码

// 这是bootstraptable代码部分
<table id="dbtableDefTb" data-toggle="table" data-toolbar="#toolbar"
data-search="true"
data-show-refresh="true"
data-show-toggle="true"
data-show-columns="true"
data-show-export="true"
data-detail-view="true"
data-detail-formatter="detailFormatter"
data-pagination="true"
data-page-size="50"
data-page-list="[50, 100, ALL]"
data-show-footer="false"
data-side-pagination="server"
data-url="${pageContext.request.contextPath}/dbtableDef/select/cols.oem">
<thead>
<tr>
<th data-field="" data-checkbox="true"></th>
<th data-field="" data-formatter="viewIndex">序号</th>
<th data-field="" data-formatter="viewOptions">操作</th>
<th data-field="dbColName" data-formatter="editCol">数据表字段名称</th>
<th data-field="mdColName" data-formatter="editCol">模型表字段名称</th>
<th data-field="dataType" data-formatter="editColDataType">数据类型</th>
<th data-field="dataTypeLen" data-formatter="editCol">数据长度</th>
<th data-field="isNull" data-formatter="editColIsNull">是否可空</th>
<th data-field="colDescribe" data-formatter="editCol">描述</th>
<th data-field="orderBy" data-formatter="editCol">排序值</th>
</tr>
</thead>
</table>

上面的这些函数,在下面的代码里都可以找到对应的出处

function editCol(value, row, index, key){
return "<div><input type=\"text\" value=\"" + value + "\" onchange='reloadRowData($(this), " + JSON.stringify(row) + ", \"" + key + "\", " + index + ")' /></div>";
} function editColDataType(value, row, index, key){
var selectNotNullStr = 'selected="selected"';
var selectNullStr = '';
var html = [];
html.push("<select onchange='reloadRowData($(this), " + JSON.stringify(row) + ", \"" + key + "\", " + index + ")'>");
// dataTypeSelect 是在加载页面的时候用 ajax 到后台取出的值,作为这个页面的全局变量赋给了 dataTypeSelect
$.each(dataTypeSelect, function(index, content){
html.push('<option value="' + content.id + '" ' + (value==content.id ? selectNotNullStr : selectNullStr) + '>' + content.text + '</option>');
});
html.push('</select>'); return html.join('');
} function editColIsNull(value, row, index, key){
var selectNotNullStr = 'selected="selected"';
var selectNullStr = '';
return [
"<select onchange='reloadRowData($(this), " + JSON.stringify(row) + ", \"" + key + "\", " + index + ")'>",
'<option value="1" ' + (value==1 ? selectNotNullStr : selectNullStr) + '>可以为空</option>',
'<option value="0" ' + (value==0 ? selectNotNullStr : selectNullStr) + '>不可为空</option>',
'</select>'
].join('');
} function viewIndex(value, row, index){
return '<div>' + (index + 1) + '</div>';
} // 改变 input 编辑框值时,更新 data 数据,便于新增行时原来填写好的数据不会被新增行强制覆盖
function reloadRowData(obj, row, key, index){
row[key] = obj.val();
$('#dbtableDefTb').bootstrapTable('getOptions').data.splice(index, 1, row);
} function viewOptions(value, row, index){
return [
"<a class=\"like\" href='javascript:addRow(" + index + ", " + JSON.stringify(row) + ")' title=\"新增行\">",
'<i class="glyphicon glyphicon-plus"></i>',
'</a> ',
'<a class="remove" href="javascript:removeRow(\'' + row.dbColName + '\')" title="删除行">',
'<i class="glyphicon glyphicon-remove"></i>',
'</a>'
].join('');
} function addRow(insertIndex, rowObj){
var insertRow = rowObj;
$.each(insertRow, function(name, value){
insertRow[name] = '';
}); var params = {index:insertIndex + 1, row:insertRow};
$('#dbtableDefTb').bootstrapTable('insertRow', params);
}

细心的朋友会发现, bootstraptable documentation 描述的 column method ,在 data-formatter 回调函数执行的时候是只有三个参数的 ,怎么我这里 function editColIsNull(value, row, index, key) 是四个参数,那个 key 是哪里来的?答案就是,这是我为了实现方便,改了 bootstraptable 源码,

// 添加 field 参数给 formatters 属性
value = calculateObjectValue(column,
that.header.formatters[j], [value, item, i, field], value);

以上代码写好后,再去新增就不会有问题了。

额外的好处

因为是动态编辑行,所以在我们编辑好后,需提交后台保存的时候,如果按传统的模式,我们还需逐个迭代这个 $(‘#dbtableDefTb’) 去把填好的内容打包,在后台再解包,很多不优雅的代码,但是通过在编辑的时候加入 onchange 事件,基本上就是实时更新 table data 数据,因为 data 天然就是 json 数据,所以我们在提交的 时候不用做什么处理,就可以直接提交

function addModel(){
// $('#qry_db_form') 是主表的 form 数据,通过 serializeObject() 方法转换成对象
var addObj = $('#qry_db_form').serializeObject();
// 在 addObj 对象里添加名称为 hiddenDbtableColDefs 数组,即为 bootstraptable data 数组对象
addObj['hiddenDbtableColDefs'] = $('#dbtableDefTb').bootstrapTable('getData');
var url = '${pageContext.request.contextPath}/dbtableDef/addModelDb?${_csrf.parameterName}=${_csrf.token}';
$.postJSON(url, addObj, function(result){
if(result.state == 1){
$.messager.alert("成功", result.message);
}else{
$.messager.alert("失败", result.message);
}
});
} $.postJSON = function(url, data, callback) {
return jQuery.ajax({
'type': 'POST',
'url': url,
'contentType': 'application/json',
'data': JSON.stringify(data),
'dataType': 'json',
'success': callback,
'error': errorHandler
});
};

后台 spring mvc 代码如下

@RequestMapping(value = "addModelDb", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public Message addModelDb(@RequestBody DbtableDef dbtableDef) throws Exception {
try {
this.dbtableDefService.insert(dbtableDef);
return new Message(Message.SUCCESS, "保存数据模型成功!");
} catch (Exception e) {
e.printStackTrace();
return new Message(Message.FAILED, "保存数据模型失败!");
}
}

实体 bean 记得添加名为 hiddenDbtableColDefs 的 list 对象,并设置 get 和 set 方法

@Transient
private List<DbtableColDef> hiddenDbtableColDefs; public List<DbtableColDef> getHiddenDbtableColDefs() {
return hiddenDbtableColDefs;
} public void setHiddenDbtableColDefs(List<DbtableColDef> hiddenDbtableColDefs) {
this.hiddenDbtableColDefs = hiddenDbtableColDefs;
}

在 Bootstraptable 插件基础上新增可编辑行的更多相关文章

  1. 01-vscode自定义配色方案 插件基础上

    01-下载相关主题插件 02- 点击设置按钮 复制id 03-进入插件文件 C:\Users\Administrator\.vscode\extensions 04-复制刚才的id 05-themes ...

  2. 基于Metronic的Bootstrap开发框架经验总结(18)-- 在代码生成工具Database2Sharp中集成对Bootstrap-table插件的分页及排序支持

    在我们开发系统界面,包括Web和Winform的都一样,主要的界面就是列表展示主界面,编辑查看界面,以及一些辅助性的如导入界面,选择界面等,其中列表展示主界面是综合性的数据展示界面,一般往往需要对记录 ...

  3. 如何基于Winform开发框架或混合框架基础上进行项目的快速开发

    在开发项目的时候,我们为了提高速度和质量,往往不是白手起家,需要基于一定的基础上进行项目的快速开发,这样可以利用整个框架的生态基础模块,以及成熟统一的开发方式,可以极大提高我们开发的效率.本篇随笔就是 ...

  4. 在cocos code ide的基础上构建自己的lua开发调试环境

    对于一种语言,其所谓开发调试环境, 大体有以下两方面的内容: 1.开发, 即代码编写, 主要是代码提示.补齐, 更高级一点的如变量名颜色等. 2.调试, 主要是运行状态下断点.查看变量.堆栈等. 现在 ...

  5. Eclipse插件基础篇一

    名词翻译 有一些名词在翻译的过程中可能会出现歧义,在这里统一一下. アーキテクチャ=architecture=架构 プラットフォーム=platform=平台 コンポーネント=component=组件 ...

  6. BootstrapTable插件的使用 【转】

    一.什么是Bootstrap-table? 在业务系统开发中,对表格记录的查询.分页.排序等处理是非常常见的,在Web开发中,可以采用很多功能强大的插件来满足要求,且能极大的提高开发效率,本随笔介绍这 ...

  7. jQuery 插件基础

    jQuery 插件基础 翻译 How to Create a Basic Plugin 如果你需要在 jQuery 选择器上执行一系列重复操作, 这时候你需要编写 jQuery 插件. jQuery ...

  8. Html5实现头像上传和编辑,保存为Base64的图片过程

    一.Html5实现头像上传和编辑 插件地址: html5手机端裁剪图片上传头像代码 本地项目引入注意事项: 1.将html的js搬到外面的js文件中,便于管理 2.图片样式在html都是在页面写死,需 ...

  9. 一种安全云存储方案设计(下)——基于Lucene的云端搜索与密文基础上的模糊查询

    一种安全的云存储方案设计(未完整理中) 一篇老文了,现在看看错漏颇多,提到的一些技术已经跟不上了.仅对部分内容重新做了一些修正,增加了一些机器学习的内容,然并卵. 这几年来,云产品层出不穷,但其安全性 ...

随机推荐

  1. HNOI 2016 地图

    [题目描述] Hoshizora Rin是个特别好动的少女. 一天Rin来到了一个遥远的都市.这个都市有N个建筑,编号从1到N,其中市中心编号为1,这个都市有M条双向通行的街道,每条街道连接着两个建筑 ...

  2. ASP.NET 设置DropDownList的当前选项

    1.通过显示字符Text DropDownList.Items.FindByText("你的值").Selected=true; 如果在设置之前,进行过设置,应用如下格式: Dro ...

  3. hdu 1016 Prime Ring Problem (素数环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1016 题目大意:输入一个n,环从一开始到n,相邻两个数相加为素数. #include <iost ...

  4. Quartz的Properties文件解析

    将可变信息放在properties文件是使配置更加灵活. 1.文档位置和加载顺序 1. StdSchedulerFactory默认加载quartz包下的quartz.properties文件,如果我们 ...

  5. php中类的static变量使用

    <?php #访问静态变量 #类外部: 类名::$类变量名 #类内部: 娄名::$类变量名或self::$类变量名 class Char{ public static $number = 0; ...

  6. inet_select_addr

    当通过输出设备向目的地址发送报文时,如果没有源地址,则需要调用inet_select_addr来选择ip地址作为源地址: /* 选择ip地址 通过设备找到ip控制块,从ip控制块中遍历地址列表中的主地 ...

  7. 多线程伪共享FalseSharing

    1. 伪共享产生: 在SMP架构的系统中,每个CPU核心都有自己的cache,当多个线程在不同的核心上,并且某线程修改了在同一个cache line中的数据时,由于cache一致性原则,其他核心cac ...

  8. (二十)ubuntu的recovery mode解决用户一些实际问题

    遇到的问题如下: 1.在当前用户下使用sudo来直接修改password等几个文件,一旦修改了passwd,用户名发生了变化,其他的用户组.密码等却没有对应的配置,就再进不了该用户了. 2.忘记用户密 ...

  9. 2015多校第8场 HDU 5382 GCD?LCM! 数论公式推导

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5382 题意:函数lcm(a,b):求两整数a,b的最小公倍数:函数gcd(a,b):求两整数a,b的最 ...

  10. DXEditingRow的错误原因

    原因之一:例如commbox理由id这一列但是数据库表中没有的话就会报这个错误