论坛首页 Web前端技术论坛

Extjs4.1 TreePanel 的增删改查与拖拽排序

浏览 8549 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-04-27  
用了一天的时间完成了对Extjs TreePanel的 增删改查与拖拽排序

一来对自己写的代码做一个总结,二来给有需要的人一些帮组,

如果代码有什么BUG或者更好的建议,欢迎大家留言


先看效果图




/**
 * 定义树节点
 */
public class TreeNode {

	//ID
	private int id;
	
	//展示数时显示的文本
	private String text;
	
	//是否是叶子节点
	private boolean leaf;
	
	//子节点的集合
	//(@JsonInclude(Include.NON_NULL)序列化时的标记 如果为空则不参与序列化)
	@JsonInclude(Include.NON_NULL)  
	private List<TreeNode> children;

	public TreeNode() {}
	
	public TreeNode(int id, String text, boolean leaf) {
		super();
		this.id = id;
		this.text = text;
		this.leaf = leaf;
	}

	public TreeNode(int id, String text, boolean leaf, List<TreeNode> children) {
		super();
		this.id = id;
		this.text = text;
		this.leaf = leaf;
		this.children = children;
	}
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public boolean isLeaf() {
		return leaf;
	}

	public void setLeaf(boolean leaf) {
		this.leaf = leaf;
	}

	public List<TreeNode> getChildren() {
		return children;
	}

	public void setChildren(List<TreeNode> children) {
		this.children = children;
	}
}



package com.sshe.operation.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.sshe.base.controller.BaseController;
import com.sshe.operation.entity.TreeNode;

/**
 * 控制层,我用的Spring3 MVC
 * 4个方法分别与Extjs的API对应
 * api: {
 *	    create: 'TreeApiController.do?method=createTreeNode',
 *	    read: 'TreeApiController.do?method=queryTreeList',
 *	    update: 'TreeApiController.do?method=updateTreeNode',
 *	    destroy: 'TreeApiController.do?method=destroyTreeNode'
 * }
 */
@Controller
@RequestMapping("/TreeApiController.do")
public class TreeApiController extends BaseController {

	/**
	 * 查询的方法
	 * 对应 read: 'TreeApiController.do?method=queryTreeList'
	 */
	@ResponseBody
	@RequestMapping(params="method=queryTreeList")
	public Object queryTreeList(ModelMap map) {
		System.out.println(map);
		JsonResult result = new JsonResult();
		result.setSuccess(true);
		result.setData(getTreeList());
		return getTreeList();
	}
	
	/**
	 * 新增方法
	 * 对应create: 'TreeApiController.do?method=createTreeNode'
	 */
	@ResponseBody
	@RequestMapping(params="method=createTreeNode")
	public Object createTreeNode(ModelMap map) {
		System.out.println(map);
		JsonResult result = new JsonResult();
		result.setSuccess(true);
		return result;
	}
	
	/**
	 * 更新的方法
	 * 对应 update: 'TreeApiController.do?method=updateTreeNode'
	 */
	@ResponseBody
	@RequestMapping(params="method=updateTreeNode")
	public Object updateTreeNode(ModelMap map) {
		System.out.println(map);
		JsonResult result = new JsonResult();
		result.setSuccess(true);
		return result;
	}
	
	/**
	 * 删除的方法
	 * 对应 destroy: 'TreeApiController.do?method=destroyTreeNode'
	 */
	@ResponseBody
	@RequestMapping(params="method=destroyTreeNode")
	public Object destroyTreeNode(ModelMap map) {
		System.out.println(map);
		JsonResult result = new JsonResult();
		result.setSuccess(true);
		return result;
	}
	
	/**
	 * 测试数据
	 */
	public List<TreeNode> getTreeList() {
		List<TreeNode> list = new ArrayList<TreeNode>();
		
		TreeNode java = new TreeNode(1, "java-1", false, new ArrayList<TreeNode>());
		TreeNode hibernate = new TreeNode(2, "hibernate-2", true);
		TreeNode spring = new TreeNode(3, "spring-3", true);
		TreeNode struts = new TreeNode(4, "struts-4", true);
		java.getChildren().add(hibernate);
		java.getChildren().add(spring);
		java.getChildren().add(struts);
		
		TreeNode javascript = new TreeNode(5, "javascript-5", false, new ArrayList<TreeNode>());
		TreeNode extjs = new TreeNode(6, "extjs-6", false, new ArrayList<TreeNode>());
		javascript.getChildren().add(extjs);
		TreeNode extPlugin = new TreeNode(7, "extPlugin-7", true);
		extjs.getChildren().add(extPlugin);
		
		list.add(java);
		list.add(javascript);
		
		return list;
	}
}



		Ext.onReady(function() {
			
			//GUID
			function newGuid() {
			    var guid = "";
			    for (var i = 1; i <= 32; i++){
			      var n = Math.floor(Math.random()*16.0).toString(16);
			      guid +=   n;
			      if((i==8)||(i==12)||(i==16)||(i==20))
			        guid += "-";
			    }
			    return guid;    
			}  
			
			//Toopitp
			Ext.tip.QuickTipManager.init();
			
			//定义菜单
			Ext.define('SimpleTasks.view.lists.ContextMenu', {
			    extend: 'Ext.menu.Menu',
			    xtype: 'listsContextMenu',
			    items: [
			        {
			            text: 'New List',
			            iconCls: 'tasks-new-list',
			            id: 'new-list-item'
			        },
			        {
			            text: 'New Folder',
			            iconCls: 'tasks-new-folder',
			            id: 'new-folder-item'
			        },
			        {
			            text: 'Delete',
			            iconCls: 'tasks-delete-folder',
			            id: 'delete-folder-item'
			        }
			    ]
			
			});
			
			//Model
			Ext.define('MyTreeModel', {
		        extend: 'Ext.data.Model',
		        fields: [
		            {name: 'id',     type: 'string'},
		            {name: 'text',     type: 'string'},
		            {name: 'index', type: 'int', persist: true}
		        ]
		    });
    
			//Store
			Ext.define("MyTreeStore", {
				extend: "Ext.data.TreeStore",
				model: 'MyTreeModel',
				proxy: {
			        type: 'ajax',
			        api: {
			            create: 'TreeApiController.do?method=createTreeNode',
			            read: 'TreeApiController.do?method=queryTreeList',
			            update: 'TreeApiController.do?method=updateTreeNode',
			            destroy: 'TreeApiController.do?method=destroyTreeNode'
			        },
			        writer: {
			        	type: 'json',
			        	allowSingle: false,
			        	encode: true,
			        	root: 'records'
			        }
			    },
		        root: {
		        	id: -1,
		            expanded: true,
		            text: "My Root"
		        },
			    autoLoad: true
			});
			

			
			var store = Ext.create("MyTreeStore");
			
			Ext.define("MyTreePanel", {
				extend: 'Ext.tree.Panel',
			    title: 'Simple Tree',
			    width: 250,
			    height: 400,
			    store: store,
			    hideHeaders: true,
			    rootVisible: true,
		        viewConfig: {
		            plugins: {
		                ptype: 'treeviewdragdrop'
		            },
		            listeners: {
		                drop: function(node, data, dropRec, dropPosition) {
		                    store.sync();
		                }
		            }
		        },
		        
			    initComponent: function() {
			    	var me = this;
			    	//可编辑
			    	me.plugins = [me.cellEditingPlugin = Ext.create('Ext.grid.plugin.CellEditing')];
			    	
			    	//定义列
			    	me.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: 'resources/images/delete.png',
		                iconCls: 'x-hidden',
		                tooltip: 'Delete',
		                handler: Ext.bind(me.handleDeleteClick, me)
				    }];
				    
				    //定义底部tbar
				    me.dockedItems = [{
			            xtype: 'toolbar',
			            dock: 'bottom',
			            items: [{
		                    iconCls: 'tasks-new-list',
		                    tooltip: 'New List',
		                    handler: me.handleNewListClick,
		                    scope: me
			            },{
		                    iconCls: 'tasks-new-folder',
		                    tooltip: 'New Folder',
		                    handler: me.handleNewFolderClick,
		                    scope: me
			            },{
		                    iconCls: 'tasks-delete-folder',
		                    id: 'delete-folder-btn',
		                    tooltip: 'Delete Folder'
			            }]
			        }];
			        
				    me.contextMenu = Ext.create("SimpleTasks.view.lists.ContextMenu");
				    
			    	me.callParent();
			    	
			    	me.on("itemmouseenter", me.showActions);
			    	me.on("itemmouseleave", me.hideActions);
			    	me.on("edit", me.updateNode);
			    	me.on("afterrender", me.handleAfterListTreeRender);
			    	me.on("beforeedit", me.handleBeforeEdit, me);
			    	//me.on("canceledit", me.handleCancelEdit);
			    	me.on("itemcontextmenu", me.showContextMenu, me);
			    },
			    
			    //刷新树
			    refreshView: function() {
			         //refresh the data in the view.  
			         //This will trigger the column renderers to run, 
			        this.getView().refresh();
			    },
			    
			    //显示actioncolumn
			    showActions: function(view, list, node, rowIndex, e) {
			        var icons = Ext.DomQuery.select('.x-action-col-icon', node);
			        if(view.getRecord(node).get('id') != "-1") {
			            Ext.each(icons, function(icon){
			                Ext.get(icon).removeCls('x-hidden');
			            });
			        }
			    },
			    
			    //隐藏actioncolumn
			    hideActions: 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');
			        });
			    },
			    
			    //Handles a click on a delete icon
			    handleDeleteClick: function(gridView, rowIndex, colIndex, column, e, record) {
			    	//这个model区别于普通的model
			    	//在定义store的时候并没有定义fields或model属性,该model由treeStore自动创建
			    	//该model包含树展示所需要的数据结构,具备parentNode,isLeaf,loaded等属性
			    	var model = gridView.getRecord(gridView.findTargetByEvent(e));
			    	this.deleteNode(model);
			    },
			    
			    //删除节点
			    deleteNode: function(nodel) {
			    	nodel.parentNode.removeChild(nodel);
			    	//与服务器端同步
			    	store.sync();
			    },
			    
			    //更新节点
			    updateNode: function(editor, e) {
			    	var me = this;
			    	//与服务器端同步
			    	store.sync();
			    },
			    
			    //树加载完毕后设置默认选中第一个
			    handleAfterListTreeRender: function(tree) {
			    	tree.getSelectionModel().select(0);
			    },
			    
			    //编辑前判断跟节点不允许编辑
			    handleBeforeEdit: function(editingPlugin, e) {
			        return e.record.get('id') !== -1;
			    },
			    
			    //取消编辑事件
			    handleCancelEdit: function(editor, e) {
			        var list = e.record,
			            parent = list.parentNode;
			        parent.removeChild(list);
			        this.getListTree().getSelectionModel().select([parent]);
			    },
			    
			    //添加叶子节点
			    handleNewListClick: function(component, e) {
			        this.addNode(true);
			    },
			    
			    //添加跟节点
			    handleNewFolderClick: function(component, e) {
			        this.addNode();
			    },
			    
			    //添加节点
			    addNode: function(leaf) {
			    	var me = this;
			    	var listTree = me;
		            cellEditingPlugin = listTree.cellEditingPlugin,
		            selectionModel = listTree.getSelectionModel(),
		            selectedList = selectionModel.getSelection()[0],
		            parentList = selectedList.isLeaf() ? selectedList.parentNode : selectedList,
		            newList = Ext.create('MyTreeModel', {
		            	id: newGuid(),
		                text: 'New ' + (leaf ? 'List' : 'Folder'),
		                leaf: leaf,
		                loaded: true // set loaded to true, 
		                			 //so the tree won't try to dynamically load children 
		                			 //for this node when expanded
		            }),
		            expandAndEdit = function() {
		                if(parentList.isExpanded()) {
		                    selectionModel.select(newList);
		                    cellEditingPlugin.startEdit(newList, 0);
		                } else {
		                    listTree.on('afteritemexpand', function startEdit(list) {
		                        if(list === parentList) {
		                            selectionModel.select(newList);
		                            cellEditingPlugin.startEdit(newList, 0);
		                            // remove the afterexpand event listener
		                            listTree.un('afteritemexpand', startEdit);
		                        }
		                    });
		                    parentList.expand();
		                }
		            };
			        parentList.appendChild(newList);
			        if(listTree.getView().isVisible(true)) {
			            expandAndEdit();
			        } else {
			            listTree.on('expand', function onExpand() {
			                expandAndEdit();
			                listTree.un('expand', onExpand);
			            });
			            listTree.expand();
			        }
			    },
			    
			    //添加右键菜单
			    showContextMenu: function(view, list, node, rowIndex, e) {
			    	this.contextMenu.showAt(e.getX(), e.getY());
			    	e.preventDefault();
			    }
			});
			
			Ext.create("MyTreePanel", {
				renderTo: Ext.getBody()
			});
		});



源码压缩后太大无法上传,需要的留邮箱我发给大家
  • 大小: 19.4 KB
   发表时间:2013-04-28  
谢谢大神 !我的邮箱:danyijiangnan@163.com  希望能够得到源码进一步学习
1 请登录后投票
   发表时间:2013-04-28  
不错的,最近我刚好在学习!
0 请登录后投票
   发表时间:2013-04-28  
danyijiangnan 写道
谢谢大神 !我的邮箱:danyijiangnan@163.com  希望能够得到源码进一步学习

http://yunpan.cn/QW6kf57qZLTfB 这个是源码的下载地址
0 请登录后投票
   发表时间:2013-05-04  
ext4.1的稳定性如何,在项目中有使用过吗
0 请登录后投票
   发表时间:2013-05-04  
jacking124 写道
ext4.1的稳定性如何,在项目中有使用过吗

可以啊,我们已经开发几个项目了。完成了很多以前不好实现的功能,比如表格内的编辑。看你们开发什么样的项目,如果是数据密集型的,只针对数据 表格 报表 图表打交道的话 EXT还是不错的选择
0 请登录后投票
   发表时间:2013-05-05  
跟风求源码。astralias@gmail.com
0 请登录后投票
   发表时间:2013-05-31  
好东西

http://www.ins24.com/page.html?dbid=5190999f159df7475b00001b&pageid=5194490c1d9bf3266200004b
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics