承接着上一篇,在TreePanel的节点上应用CellEditor插件对节点进行修改,上一篇《ExtJS5学习之TreePanel》中节点数据修改是通过弹出一个Window实现的,这次我们来试试使用CellEditor插件来完成同样的功能,关键代码如下:
/*****************ExtJS TreePanel面板*********************/ Ext.define("OA.view.TreePanel",{ extend:'Ext.tree.Panel', alias : 'widget.mytreepanel', alternateClassName: ["OA.TreePanel"], initComponent : function(){ Ext.apply(this,{ title:"导航菜单", animate:true, animCollapse: true, autoScroll : true, scroll: "vertical", rootVisible : false, lines: false, useArrows: true, containerScroll: true, collapsed: false, collapsible: false, layout: "fit", border: false, width: 200, dockedItems: { dock : 'top', xtype : 'toolbar', items : [ { xtype : 'button', text : '刷新' }, { xtype : 'button', text : '展开' }, { xtype : 'button', text : '收缩' } ] }, viewConfig : { loadingText : "正在加载...", plugins: { ptype: 'treeviewdragdrop' }, listeners: { drop: function(node, data, dropRec, dropPosition) { //store.sync(); } } }, store: Ext.create("OA.store.TreeStore") }); this.plugins = [{"ptype": "cellediting"}]; this.columns = [ { xtype: 'treecolumn', dataIndex: 'text', flex: 1, editor: { xtype: 'textfield', selectOnFocus: true, validator: function(value){ value = Ext.String.trim(value); return value.length < 1 ? this.blankText : true; } } }, { xtype: 'actioncolumn', width: 24, icon: 'delete.png', iconCls: 'x-hidden', tooltip: 'Delete' } ]; this.callParent(arguments); } });
关键点1在:
this.plugins = [{"ptype": "cellediting"}];
这里表示添加celleditor插件,添加了该插件之后,双击树节点可以对节点名称进行修改,默认该插件是双击进入编辑模式,当然你也可以通过修改clickToEdit值来改变这种默认行为,比如
this.plugins = [{"ptype": "cellediting","clickToEdit":1}];
"clickToEdit":1即表示点击节点一次就可进入编辑模式,默认该值为2.
关键点2在:
this.columns = [ { xtype: 'treecolumn', dataIndex: 'text', flex:4, width: 100, editor: { xtype: 'textfield', selectOnFocus: true, allowBlank: false, allowOnlyWhitespace: false } }, { xtype: 'actioncolumn', itemId: "deleteCol", flex:1, icon: 'delete.png', tooltip: 'Delete', iconCls: 'x-hidden' } ];
这里定义了两列,一列用于显示节点数据,一列用于显示操作按钮或者说操作图标即xtype:"actioncolumn"。flex:1这里的flex表示定义这两列的宽度比例,如果一个flex:4,一个flex:1即表示这两列的显示宽度比例是4:1,你懂的。icon是显示图标资源文件的路径,tooltip是鼠标放在图标上时弹出的文字提示,iconCls是当前图标应用的CSS类样式,x-hidden是我自定义的css类样式,定义在index.jsp里
<style type="text/css"> .x-hidden { visibility: hidden !important } </style>
visibility: hidden !important表示隐藏不显示
剩下的就是监听事件做相应的逻辑处理,事件监听写在Controller里,代码如下:
/*******************全局应用程序控制器类******************/ //首先载入工具类 Ext.require( [ 'OA.util.CommonDoActionUtil' ] ); Ext.define('OA.controller.AppController', { extend: 'Ext.app.Controller', requires: ['OA.util.CommonDoActionUtil'], //数据模型注册 models: [ 'TreeModel' ], //视图注册 views: ["TreePanel","TreeContextMenu","TreeEditWindow"], //数据源注册 stores: [ 'TreeStore' ], init: function() { var id_ = 111; var currentRecord = null; this.control({ "mytreepanel": { itemcontextmenu: function(_this, record, item, index, evt, eOpts) { if(!this.ctxMenu) { this.ctxMenu = Ext.create("OA.view.TreeContextMenu"); } this.ctxMenu.showAt(evt.getXY()); //缓存当前鼠标右键选中的节点数据Name currentRecord = record; evt.preventDefault(); //evt.stopEvent(); _this.getSelectionModel().select(index); }, //鼠标进入时显示ActionColumn itemmouseenter: function(view, list, node, rowIndex, e) { var icons = Ext.DomQuery.select('.x-action-col-icon', node); if(view.getRecord(node).get('id') != 0) { Ext.each(icons, function(icon){ Ext.get(icon).removeCls('x-hidden'); }); } }, //鼠标离开时隐藏ActionColumn itemmouseleave: function(view, list, node, rowIndex, e) { var icons = Ext.DomQuery.select('.x-action-col-icon', node); Ext.each(icons, function(icon){ Ext.get(icon).addCls('x-hidden'); }); }, containerclick: function(_this,e,eOpts) { if(this.ctxMenu) { this.ctxMenu.hide(); } }, //编辑完成后触发 edit: function(editor,e) { e.record.commit(); console.log(e.record.get("text")); } }, "treecontextmenu > menuitem[itemId=add]": { click: function(item, event, eOpts) { if(currentRecord) { currentRecord.appendChild( { id: id_++, "text": "测试节点_" + id_, "leaf": true } ); //展开当前节点 currentRecord.expand(); //发送ajax请求到后台插入添加的节点数据,你懂的 } } }, "treecontextmenu > menuitem[itemId=edit]": { click: function(item, event, eOpts) { if(currentRecord) { if(!this.editWin) { this.editWin = Ext.create("OA.view.TreeEditWindow"); } this.editWin.show(); } } }, "treecontextmenu > menuitem[itemId=delete]": { click: function(item, event, eOpts) { if(currentRecord) { currentRecord.parentNode.removeChild(currentRecord); currentRecord.commit(); } } }, "treeeditwindow button[itemId=ok]": { click: function(_this, e, eOpts ) { if(currentRecord) { //获取表单数据 var formData = _this.up("treeeditwindow").down("form").getForm().getValues(); var nodeText = formData.nodeName; //修改节点数据 currentRecord.set("text",nodeText); currentRecord.commit(); //同理,发送Ajax请求到后台修改节点数据 } //关闭窗体 _this.up("treeeditwindow").hide(); } }, "treeeditwindow button[itemId=cancle]": { click: function(_this, e, eOpts ) { _this.up("treeeditwindow").hide(); } }, //点击删除小图标时删除当前树节点 "actioncolumn[itemId=deleteCol]": { click: function(gridView, rowIndex, colIndex, column, e, record) { //获取当前删除小图标所处行的树节点的数据 var model = gridView.getRecord(gridView.findTargetByEvent(e)); console.log(model.parentNode); model.parentNode.removeChild(model); model.commit(); //这里是演示下在当前事件里如何获取当前TreePanel对象 console.log(gridView.up("mytreepanel")); //gridView.up("mytreepanel").deleteNode(model); } } }); this.commonAction = Ext.create('OA.util.CommonDoActionUtil'); } });
在上一篇的基础上多监听了几个事件,比较重要的就是如何编写组件查询表达式,;类似于JQuery的选择器表达式,懂JQuery的话,应该会举一反三。下面对一些重点进行说明:
//编辑完成后触发 edit: function(editor,e) { e.record.commit(); console.log(e.record.get("text")); }
这里是监听cellEditor插件在退出编辑模式完成编辑时触发的动作,首先通过e.record获取到你修改后新的节点名称数据,e.record是一个Ext.data.Model类的对象,你可以通过e.record.get("属性名")来获取相应属性值,有了修改后的数据,剩下就是把数据通过ajax方式发送到后台更新到数据库,demo里并没有提供跟后台交互的示例代码,留给你们自己去完成。
//点击删除小图标时删除当前树节点 "actioncolumn[itemId=deleteCol]": { click: function(gridView, rowIndex, colIndex, column, e, record) { //获取当前删除小图标所处行的树节点的数据 var model = gridView.getRecord(gridView.findTargetByEvent(e)); console.log(model.parentNode); model.parentNode.removeChild(model); model.commit(); //这里是演示下在当前事件里如何获取当前TreePanel对象 console.log(gridView.up("mytreepanel")); //gridView.up("mytreepanel").deleteNode(model); } }
这里是监听删除小图标的单击事件,点击后删除当前树节点,代码逻辑里面有详细注释,就不再啰嗦了。同理,这里也并没有与后台交互的代码,实际可能需要在这里发送Ajax请求到后台去删除该节点数据的,你懂的哈!
//鼠标进入时显示ActionColumn itemmouseenter: function(view, list, node, rowIndex, e) { var icons = Ext.DomQuery.select('.x-action-col-icon', node); if(view.getRecord(node).get('id') != 0) { Ext.each(icons, function(icon){ Ext.get(icon).removeCls('x-hidden'); }); } }, //鼠标离开时隐藏ActionColumn itemmouseleave: function(view, list, node, rowIndex, e) { var icons = Ext.DomQuery.select('.x-action-col-icon', node); Ext.each(icons, function(icon){ Ext.get(icon).addCls('x-hidden'); }); },
这两处是实现鼠标悬浮进入时显示删除小图标,鼠标离开时隐藏删除小图标,这个仅仅是玩了一个JS效果,没什么实际用途,可加可不加。
最后照例弄几张效果图,不然光代码不够形象,
如果你仍有什么疑问或者你需要demo源代码,请加我QQ:7-3-6-0-3-1-3-0-5,或者加裙一起交流学习: