昨天写了一个ko+easyui的同样的实现,感觉写的太乱,用起来十分麻烦,于是今天照着edatagrid,写了一个etreegrid,这样再用ko绑定就方便多了。 使用很简单,$(tableId).etreegrid({idField:''parentIdField:'',treeField:'',saveUrl:'',deleteUrl:''}); 还支持一些事件,onSave,onBeforeSave,onEdit,onAdd,onRemove; Url可以不指定,指定Data即可。
/** * etreegrid - jQuery EasyUI * * Licensed under the GPL: * http://www.gnu.org/licenses/gpl.txt * * Copyright 2013 maddemon [ [email protected] ] * * Dependencies: * treegrid * messager * */ (function ($) { function buildGrid(target) { var opts = $.data(target, 'etreegrid').options; $(target).treegrid($.extend({}, opts, { onDblClickCell: function (field, row) { if (opts.editing) { $(this).etreegrid("editRow", row); focusEditor(field); } }, onClickCell: function (field, row) { if (opts.editing && opts.editIndex >= 0) { if (!trySaveRow()) { focusEditor(field); return; } } }, onAfterEdit: function (row, changes) { opts.editIndex = undefined; var url = row.isNewRecord ? opts.saveUrl : opts.updateUrl; if (url) { $.post(url, row).done(function (json, statusText, xhr) { if (row.isNewRecord) { row.isNewRecord = false; //remove new $(target).treegrid("remove", row[opts.idField]); row[opts.idField] = json[opts.idField] || json.data[opts.idField]; $(target).treegrid("append", { parent: row[opts.parentIdField], data: [row] }); //append new } else { //refresh $(target).treegrid("refresh", row[opts.idField]); } }).error(function (xhr) { var result = eval("(" + xhr.responseText + ")"); $.messager.alert("失败", result.message || result, "warning"); }); opts.onSave.call(target, row); } else { opts.onSave.call(target, row); } if (opts.onAfterEdit) opts.onAfterEdit.call(target, row); }, onCancelEdit: function (row) { opts.editIndex = undefined; if (row.isNewRecord) { $(this).treegrid("remove", row[opts.idField]); } if (opts.onCancelEdit) opts.onCancelEdit.call(target, row); }, onBeforeLoad: function (row, param) { if (opts.onBeforeLoad.call(target, row, param) == false) { return false; }; $(this).treegrid("rejectChanges"); } })); function trySaveRow() { if (!$(target).treegrid("validateRow", opts.editIndex)) { $(target).treegrid("select", opts.editIndex); return false; } if (opts.onBeforeSave.call(this, opts.editIndex) == false) { setTimeout(function () { $(target).treegrid('select', opts.editIndex); }, 0); return false; } $(target).treegrid('endEdit', opts.editIndex); return true; } function focusEditor(field) { var editor = $(target).treegrid('getEditor', { index: opts.editIndex, field: field }); if (editor) { editor.target.focus(); } else { var editors = $(target).treegrid('getEditors', opts.editIndex); if (editors.length) { editors[0].target.focus(); } } } } $.fn.etreegrid = function (options, param) { if (typeof (options) == "string") { var method = $.fn.etreegrid.methods[options]; if (method) { return method(this, param); } else { return this.treegrid(options, param); } } options = options || {}; return this.each(function () { var state = $.data(this, "etreegrid"); if (state) { $.extend(state.options, options); } else { $.data(this, "etreegrid", { options: $.extend({}, $.fn.etreegrid.defaults, $.fn.etreegrid.parseOptions(this), options) }); } ; buildGrid(this); }); }; $.fn.etreegrid.parseOptions = function (target) { return $.extend({}, $.fn.treegrid.parseOptions(target), {}); }; $.fn.etreegrid.methods = { options: function (jq) { var opts = $.data(jq[0], "etreegrid").options; return opts; }, enableEditing: function (jq) { return jq.each(function () { var opts = $.data(this, "etreegrid").options; opts.editing = true; }); }, disableEditing: function (jq) { return jq.each(function () { var opts = $.data(this, "etreegrid").options; opts.editing = false; }); }, editRow: function (jq, row) { return jq.each(function () { var dg = $(this); var opts = $.data(this, "etreegrid").options; var index = row[opts.idField]; var editIndex = opts.editIndex; if (editIndex != index) { if (dg.treegrid("validateRow", editIndex)) { if (editIndex >= 0) { if (opts.onBeforeSave.call(this, editIndex) == false) { setTimeout(function () { dg.treegrid("select", editIndex); }, 0); return; } } dg.treegrid("endEdit", editIndex); dg.treegrid("beginEdit", index); opts.editIndex = index; var node = dg.treegrid("find", index); opts.onEdit.call(this, node); } else { setTimeout(function () { dg.treegrid("select", editIndex); }, 0); } } }); }, addRow: function (jq) { return jq.each(function () { var dg = $(this); var opts = $.data(this, "etreegrid").options; var editIndex = opts.editIndex; if (opts.editIndex >= 0) { if (!dg.treegrid("validateRow", editIndex)) { dg.treegrid("select", editIndex); return; } if (opts.onBeforeSave.call(this, opts.editIndex) == false) { setTimeout(function () { dg.treegrid('select', opts.editIndex); }, 0); return; } dg.treegrid('endEdit', opts.editIndex); } var selected = dg.treegrid("getSelected"); var parentId = selected ? selected[opts.idField] : 0; var newRecord = { isNewRecord: true }; newRecord[opts.idField] = 0; newRecord[opts.parentIdField] = parentId; dg.treegrid("append", { parent: parentId, data: [newRecord] }); opts.editIndex = 0; dg.treegrid("beginEdit", opts.editIndex); dg.treegrid("select", opts.editIndex); }); }, saveRow: function (jq) { return jq.each(function () { var dg = $(this); var opts = $.data(this, 'etreegrid').options; if (opts.editIndex >= 0) { if (!dg.treegrid("validateRow", opts.editIndex)) { dg.treegrid("select", opts.editIndex); return; } if (opts.onBeforeSave.call(this, opts.editIndex) == false) { setTimeout(function () { dg.treegrid('select', opts.editIndex); }, 0); return; } $(this).treegrid('endEdit', opts.editIndex); } }); }, cancelRow: function (jq) { return jq.each(function () { var index = $(this).etreegrid('options').editIndex; $(this).treegrid('cancelEdit', index); }); }, removeRow: function (jq) { return jq.each(function () { var dg = $(this); var opts = $.data(this, 'etreegrid').options; var row = dg.treegrid('getSelected'); if (!row) return; if (row.isNewRecord) { dg.treegrid("remove", row[opts.idField]); return; } $.messager.confirm("确认", "确认删除这条数据吗?", function (r) { if (!r) return; var idValue = row[opts.idField]; if (opts.deleteUrl) { $.post(opts.deleteUrl, { id: idValue }).done(function (json) { dg.treegrid("remove", idValue); opts.onRemove.call(dg[0], json, row); }).error(function (xhr) { var json = eval('(' + xhr.responseText + ')'); $.messager.alert('错误', json.message || json, "warning"); }); } else { dg.datagrid('cancelEdit', idValue); dg.datagrid('deleteRow', idValue); opts.onRemove.call(dg[0], row); } }); }); } }; $.fn.etreegrid.defaults = $.extend({}, $.fn.treegrid.defaults, { editing: true, editIndex: -1, messager: {}, url: null, saveUrl: null, updateUrl: null, deleteUrl: null, onAdd: function (row) { }, onEdit: function (row) { }, onBeforeSave: function (index) { }, onSave: function (row) { }, onRemove: function (row) { }, }); })(jQuery);
knockoutjs使用此插件的方法:
<div id="area-form" fit="true"> <div id="area-tool-bar"> <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-add" plain="true" data-bind="click: add">新增</a> <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-save" plain="true" data-bind="click: save">保存</a> <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-remove" plain="true" data-bind="click: remove">删除</a> <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-cancel" plain="true" data-bind="click: cancel">取消</a> </div> <table id="area-list" rownumbers="true" title="区域列表" border="0" toolbar="#area-tool-bar" data-bind="etreegrid:tree"> <thead> <tr> <th field="Name" width="500" data-options="editor:{type:'validatebox',options:{required:true}}">地区名称</th> <th field="Code" width="120" data-options="editor:{type:'validatebox'}">地区编码</th> </tr> </thead> </table> </div> <script type="text/javascript"> (function () { var listId = "#area-list"; function AreaModel() { this.tree = { url: "/area/gettree", treeField: "Name", parentIdField: "ParentID", idField: "ID", saveUrl: "/area/save", deleteUrl: "/area/delete", }; this.add = function() { $(listId).etreegrid("addRow"); }; this.save = function () { $(listId).etreegrid("saveRow"); }; this.remove = function () { $(listId).etreegrid("removeRow"); }; this.cancel = function () { $(listId).etreegrid("cancelRow"); }; }; ko.applyBindings(new AreaModel(), document.getElementById("area-form")); })(); </script>