在 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