在 Bootstraptable 插件基础上新增可编辑行


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; } 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM