在datagrid可编辑表格里面使用Combobox多选,会出现以下问题:
1、双击编辑然后点击下拉箭头会发现所有的选项都会被选中而无法再次进行选择
2、新增一行combobox选择了多个值后,该行结束编辑时,combobox列显示空白值,选择的值根本就没有设置到单元格
下面来找下原因吧。先来分析下datagrid的beginEdit的源码:
function beginEdit(jq, rowIndex) { var opts = $.data(jq, "datagrid").options; var tr = opts.finder.getTr(jq, rowIndex); var row = opts.finder.getRow(jq, rowIndex); if (tr.hasClass("datagrid-row-editing")) { return; } if (opts.onBeforeEdit.call(jq, rowIndex, row) == false) { return; } tr.addClass("datagrid-row-editing"); createEditor(jq, rowIndex); fixEditorSize(jq); tr.find("div.datagrid-editable").each(function() { var field = $(this).parent().attr("field"); var ed = $.data(this, "datagrid.editor");//获取到Editor ed.actions.setValue(ed.target, row[field]);//调用Editor的acions里面的setValue方法赋值 }); validateRow(jq, rowIndex); };
注意这两行代码:
var ed = $.data(this, "datagrid.editor");//获取到Editor
ed.actions.setValue(ed.target, row[field]);//调用Editor的acions里面的setValue方法赋值
row[field]是行对应的combobox列的值,这个值是一个字符串,单个值时为'value1',多个值时则为'value1,value2,..,valueN'
然后我们再看下ed.actions.setValue方法:
combobox : { init : function(container, options) { var editor = $("<input type=\"text\">").appendTo(container); editor.combobox(options || {}); return editor; }, destroy : function(jq) { $(jq).combobox("destroy"); }, getValue : function(jq) { return $(jq).combobox("getValue"); }, setValue : function(jq, value) { $(jq).combobox("setValue", value); }, resize : function(jq, width) { $(jq).combobox("resize", width); } }
可以看到,action的setValue方法只是单选的值设置,而并不是多选的值设置。问题出现了。既然是多选,就应该用setValues方法,而且values应该是值数组才对啊,而不是setValue(value)啊。
解决方法,扩展改写getValue方法如下:
$.extend($.fn.datagrid.defaults.editors.combobox, { setValue : function(jq, value) { var opts = $(jq).combobox('options'); if(opts.multiple&&value.indexOf(opts.separator)!=-1){//多选且不只一个值 var values = value.split(opts.separator); $(jq).combobox("setValues", values); } else $(jq).combobox("setValue", value); } });
OK,双击编辑不能选择的问题解决了~~
下面再来看下新增行combobox多选后保存不了值的问题,同样来看datagrid的endEdit源码:
function stopEdit(jq, rowIndex, revert) { var opts = $.data(jq, "datagrid").options; var updatedRows = $.data(jq, "datagrid").updatedRows; var insertedRows = $.data(jq, "datagrid").insertedRows; var tr = opts.finder.getTr(jq, rowIndex); var row = opts.finder.getRow(jq, rowIndex); if (!tr.hasClass("datagrid-row-editing")) { return; } if (!revert) { if (!validateRow(jq, rowIndex)) { return; } var changed = false; var newValues = {}; tr.find("div.datagrid-editable").each(function() { var field = $(this).parent().attr("field"); var ed = $.data(this, "datagrid.editor"); var value = ed.actions.getValue(ed.target);//通过actions的getValue方法获取到编辑器的值,然后直接赋给单元格 if (row[field] != value) { row[field] = value; changed = true; newValues[field] = value;//把编辑器的值赋给单元格 } }); if (changed) { if (getObjectIndex(insertedRows, row) == -1) { if (getObjectIndex(updatedRows, row) == -1) { updatedRows.push(row); } } } } tr.removeClass("datagrid-row-editing"); destroyEditor(jq, rowIndex); $(jq).datagrid("refreshRow", rowIndex); if (!revert) { opts.onAfterEdit.call(jq, rowIndex, row, newValues); } else { opts.onCancelEdit.call(jq, rowIndex, row); } }
注意带注释的两行,combobox选择完然后结束编辑,endEdit是调用编辑器的action的getValue方法获取值,然后直接赋值给单元格的。那么看下combobox这个editor的getValue方法:
combobox : { init : function(container, options) { var editor = $("<input type=\"text\">").appendTo(container); editor.combobox(options || {}); return editor; }, destroy : function(jq) { $(jq).combobox("destroy"); }, getValue : function(jq) { return $(jq).combobox("getValue");//直接赋值,并没有区分是否多选 }, setValue : function(jq, value) { $(jq).combobox("setValue", value); }, resize : function(jq, width) { $(jq).combobox("resize", width); } }
呵呵,两个问题其实都是同一个原因,都没考虑多选的情况,那么同样问题可以这样解决,在上面扩展的基础上,把getValue的方法也改写下:
$.extend($.fn.datagrid.defaults.editors.combobox, { getValue : function(jq) { var opts = $(jq).combobox('options'); if(opts.multiple){ var values = $(jq).combobox('getValues'); if(values.length>0){ if(values[0]==''||values[0]==' '){ return values.join(',').substring(1);//新增的时候会把空白当成一个值了,去掉 } } return values.join(','); } else return $(jq).combobox("getValue"); }, setValue : function(jq, value) { var opts = $(jq).combobox('options'); if(opts.multiple&&value.indexOf(opts.separator)!=-1){//多选且不只一个值 var values = value.split(opts.separator); $(jq).combobox("setValues", values); } else $(jq).combobox("setValue", value); } });
到此,两个问题都解决了~~