ExtJs 3 自定义combotree

ExtJs 3 自定义combotree

/**
 * 自定义下拉树,支持初始化值时自动定位树节点。
 * 还没有考虑性能问题。继承自Ext.form.ComboBox也很浪费。
 * 代码中的cu.get()是自定义的异步请求方法。
 * @author Linzongxue
 * @create_date 2011-12-13
 */
Ext.ux.ComboBoxTree = Ext.extend(Ext.form.ComboBox, {
	//树的配置项
	dataUrl: null, //获取树所有节点的url
	//通过id获取某个节点的id全路径的url,返回值的格式应该是:parentId1/parentId2/parentId3/../节点id
	//如果不设置这个值,下拉树不会自动定位节点并在初始化时显示文本
	nodePathUrl: null,
	loader: null,
	root: {},
	rootVisible: false,
	//树的选择模式
	rootSelectable: false, //根节点是否可选,默认为false
	folderSelectable: true, //目录是否可选,默认为true
	leafSelectable: true, //叶子是否可选,默认为true
	showFullPath: false, //是否显示全路径
	rootValue: undefined, //根节点的值(通常根节点的取值与普通节点的取值不一样,如果一样则不需要设置此值)
	//原combo类的配置项
	store: new Ext.data.SimpleStore({fields:[],data:[[]]}),
	mode: ‘local‘,
	triggerAction: ‘all‘,
	editable: false,
	forceSelection: true,
	tree: null, //树控件,在expand方法中初始化
	//private: 用于防止combo收缩,在树的事件中控制此属性值
	preventCollapse: false,

	initComponent: function(){
		this.treeId = Ext.id();
		this.height = this.height || 200;
		this.tpl = String.format(‘<tpl for="."><div id="{0}" style="height:{1}px"></div></tpl>‘, this.treeId, this.height);
		Ext.ux.ComboBoxTree.superclass.initComponent.call(this);
	},
	setValue: function(value){
		if (Ext.isObject(value)){ //点击树节点时的选择
			this.doSetValue(value);
		}
		else{ //只是设置一个值,从后台获取这个值的路径,并在树中选中这个节点
			//console.log(value);
			if (!this.tree) this.initTree();
			if (value === this.tree.root.id ||
					(Ext.isDefined(this.rootValue) && value === this.rootValue)){ //根节点
				this.tree.root.select();
				this.doSetValue(this.root);
				return;
			}
			var url = this.nodePathUrl;
			if (!url){
				this.doSetValue({id: value});
				return;
			}
			cu.get(url, {id: value}).done(function(path){//从后台发起请求获取id路径
				path = ‘/‘ + this.root.id + (path.indexOf(‘/‘) == 0 ? ‘‘ : ‘/‘) + path;
				var comboTree = this;
				this.tree.selectPath(path, ‘id‘, function(success, node){
					comboTree.doSetValue(success ? node : null);
				});
			}, this);
		}
    },
    //private:设置值,参数value应该是一个对象
    doSetValue: function(value){
    	var id = value ? value.id : ‘‘;
    	var text = value ? value.text : ‘‘;
    	if (value && (value.loader || value.attributes)){ //是树节点
    		var isRootNode = (value.id == this.tree.root.id);
    		if (isRootNode && Ext.isDefined(this.rootValue)){
    			id = this.rootValue;
    		}
            if (this.showFullPath){
            	text = isRootNode ? ‘/‘ : value.getPath(‘text‘).replace(‘/‘ + this.tree.root.text, ‘‘);
            }
    	}
		this.value = id;
		if(this.hiddenField){
			this.hiddenField.value = id; //设置表单域
		}
		this.lastSelectionText = text;
		this.el.dom.value = text; //显示的值
        this.fireEvent(‘select‘, this, value);
    },
    getValue : function(){
    	return Ext.isDefined(this.value) ? this.value : ‘‘;
    },
    //取得选中的树节点
	getValueNode: function(){
		return this.tree ? this.tree.getSelectionModel().getSelectedNode() : null;
	},
	getText: function(){
		return this.lastSelectionText || ‘‘;
	},
	reload: function(){
		if (!this.tree) return;
		var node = this.tree.getSelectionModel().getSelectedNode();
		var path = node ? node.getPath() : null;
		this.tree.getLoader().load(this.tree.root, function(){
			if (path) {
				this.tree.selectPath(path);
			}
		}, this);
		this.preventCollapse = true;
	},
    //private: 根据preventCollapse属性判断是否要收缩
	collapse: function(){
		if (this.preventCollapse){
			this.preventCollapse = false;
			return;
		}
		Ext.ux.ComboBoxTree.superclass.collapse.call(this);
	},
	//private:
	expand : function(){
		Ext.ux.ComboBoxTree.superclass.expand.call(this);
		if (!this.tree){
			this.initTree();
		}
    },
    //private:
    destroy: function(){
    	if (this.tree && this.tree.rendered) this.tree.destroy();
    	Ext.form.ComboBox.superclass.destroy.call(this);
    },
    //private
    initTree: function(){
    	if (!this.list){ //必须先初始化列表,在一开始就设置了combotree的值时尤其重要,发现这个问题花了半天时间
			this.initList();
    	}
    	//设置this.preventCollapse=true,防止combo收缩
    	var enableCollapse = function(){this.preventCollapse = false;};
    	//设置this.preventCollapse=false,允许combo收缩
    	var disableCollapse = function(){this.preventCollapse = true;};
    	this.tree = new Ext.tree.TreePanel({
    		renderTo: this.treeId,
    		useArrows: false,
    	    autoScroll: true,
    	    height: this.height,  //修复IE的bug
    	    animate: true,
    	    enableDD: false,
    	    containerScroll: true,
    	    border: false,
			dataUrl: this.dataUrl,
			loader: this.loader,
			root: this.root,
			rootVisible: this.rootVisible,
//			bbar:[
//				‘->‘, {text: ‘刷新‘, handler: this.reload, iconCls: ‘icon-refresh‘, scope: this} //由于宽度问题取消此功能
//			],
			listeners: {
	        	click: function(node){
	        		disableCollapse();
		        	if (node == this.tree.root){ //选中根节点
		        		if (!this.rootSelectable) return;
		        	}
		        	else if (!node.isLeaf()){ //选中目录节点
		        		if (!this.folderSelectable) return;
		        	}
		        	else{ //选中叶子节点
		        		if (!this.leafSelectable) return;
		        	}
		        	//先选择节点,再设置value,让getNodeValue方法在select事件中取到正确的值
		        	node.select();
		        	this.setValue(node);
		        	enableCollapse();
	        	},
	        	//展开和收缩节点时防止combo收缩
	        	beforeexpandnode: disableCollapse,
	        	beforecollapsenode: disableCollapse,
	        	beforeload: disableCollapse,
	        	//节点加载和展开后允许combo收缩
	        	load: enableCollapse,
	        	expandnode: enableCollapse,
	        	scope: this
			}
    	});
    }
});
Ext.reg(‘combotree‘, Ext.ux.ComboBoxTree);

/****************  下面是一个使用例子  ***********************/
new Ext.ux.ComboBoxTree({
	fieldLabel:‘父菜单‘,
	hiddenName: ‘parentId‘,
	value: this.modifyId ? ‘‘ : this.parentMenu.id,
	height: 180,
	dataUrl: ‘sys/menu/getMenus.do‘,
	nodePathUrl: ‘sys/util/getEntityIdPath.do?c=sys.entity.Menu‘,
	root: {id:‘root‘, text:‘根菜单‘, expanded: true},
	rootVisible: true,
	rootSelectable: true,
	rootValue: null,
	showFullPath: true,
	allowBlank: false,
});

1 楼 chuanmeiwc 2011-12-29

cu.get这个方法能不能一并贴出来呢?

2 楼 chuanmeiwc 2011-12-29

chuanmeiwc 写道

cu.get这个方法能不能一并贴出来呢?

这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?

3 楼 chuanmeiwc 2011-12-30

chuanmeiwc 写道

chuanmeiwc 写道

cu.get这个方法能不能一并贴出来呢?

这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?

我的解决办法是在构造tree的时候增加一个带有清除按钮的tbar:

var combo = this;
    	this.tree = new Ext.tree.TreePanel({
    		renderTo: this.treeId,
    		useArrows: false,
    	    autoScroll: true,
    	    height: this.height,  //fix IE
    	    animate: true,
    	    enableDD: false,
    	    containerScroll: true,
    	    border: false,
			dataUrl: this.dataUrl,
			[color=red]tbar: [{text:‘清空‘,xtype:‘button‘,iconCls:‘reset‘,handler:function(){combo.setValue(null);}}],[/color]
			loader: this.loader,
			root: this.root,
			rootVisible: this.rootVisible

还有没有更好的解决办法呢?
另外还有个问题:
获取某个节点的值时只能用 Ext.getCmp(‘comboboxtree‘).getNodeValue().id 吗?我试了getValue()和getRawValue(),均不能获取到节点的id。但是使用这个方法获取节点id有个问题,只有点击了comboBox之后,才会异步获取树,因此没有点击过comboBox的时候,Ext.getCmp(‘comboboxtree‘).getNodeValue()的值为null,所以使用Ext.getCmp(‘comboboxtree‘).getNodeValue().id之前要先判断Ext.getCmp(‘comboboxtree‘).getNodeValue()是否为null,否则会报错。
这个问题你有别的办法解决吗?

4 楼 chuanmeiwc 2011-12-30

chuanmeiwc 写道

如果allowBlank设置为true,选中某个节点之后想清空值怎么办呢?

我的解决办法是在构造tree的时候增加一个带有清除按钮的tbar:

var combo = this;
    this.tree = new Ext.tree.TreePanel({
    renderTo: this.treeId,
    useArrows: false,
        autoScroll: true,
        height: this.height,  //fix IE
        animate: true,
        enableDD: false,
        containerScroll: true,
        border: false,
dataUrl: this.dataUrl,
tbar: [{text:‘清空‘,xtype:‘button‘,iconCls:‘reset‘,handler:function(){combo.setValue(null);}}],
loader: this.loader,
root: this.root,
rootVisible: this.rootVisible

还有没有更好的解决办法呢?
另外还有个问题:
获取某个节点的值时只能用 Ext.getCmp(‘comboboxtree‘).getNodeValue().id 吗?我试了getValue()和getRawValue(),均不能获取到节点的id。但是使用这个方法获取节点id有个问题,只有点击了comboBox之后,才会异步获取树,因此没有点击过comboBox的时候,Ext.getCmp(‘comboboxtree‘).getNodeValue()的值为null,所以使用Ext.getCmp(‘comboboxtree‘).getNodeValue().id之前要先判断Ext.getCmp(‘comboboxtree‘).getNodeValue()是否为null,否则会报错。
这个问题你有别的办法解决吗?

5 楼 zxlaiye 2011-12-31

chuanmeiwc 写道

chuanmeiwc 写道

cu.get这个方法能不能一并贴出来呢?

这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?

这个。。还没有考虑 ,因为才开始使用ExtJs没多久,很多应用细节还没机会去尝试。我觉得你的方法也挺好了,添加“清空”的同时顺便再加上一个“刷新”树节点的控制都不错。

6 楼 zxlaiye 2011-12-31

to chuanmeiwc

在我贴代码之后又做了一些修改,但是修改后没有及时更新上来,太多事情要处理了啊。。。
你说的通过getValue()取不到值的问题,很可能是之后解决的,不用getNodeValue().id那么麻烦。。。,另外,异步发送请求的方法cu.get(...).done(...)只是对Ext.ajax.request做了简单的封装,并且添加了全局的异常处理而已。这种写法是从jquery里学过来的,我还摆脱不了一些jquery的使用习惯。

7 楼 chuanmeiwc 2011-12-31

getValue()咋修改的呢?

8 楼 zxlaiye 2011-12-31

chuanmeiwc 写道

getValue()咋修改的呢?

getValue()方法只是简单地返回this.value,关键是doSetValue()方法中对value的设置。现在是不是可以取到正确的值了?如果是就应该是之前的doSetValue()方法有问题,具体修改了什么地方我想不起来了。。。太久了。。

9 楼 silence1214 2012-03-15

哥们 这个value的值死活出来不了

10 楼 silence1214 2012-03-15

哥,这个例子中当一个页面多次操作的时候会把上次的数据附加到这里来,比如之前树中只有1,2在打开就是1,2,1,2 只有点刷新 才可以 这是怎么回事啊,我死活找不到修改的地方

11 楼 silence1214 2012-03-16

经过昨晚一夜奋战,上午奋战。发现那个root一定要配置 哪怕是不需要。否则问题一大堆。。。

ExtJs 3 自定义combotree

时间: 2024-10-09 21:15:31

ExtJs 3 自定义combotree的相关文章

extjs_10_自定义combotree组件

1.项目截图 2.treedata.json { text : "root", expanded : true, expandable : true, children : [{ text : "Dept 1", leaf : false, expandable : true, children : [{ text : "user1", leaf : true }, { text : "user2", leaf : true

ExtJs之自定义事件

1.新建一个实践类 1 Employee = function(name) 2 { 3 4 this.name = name; 5 6 this.addEvents({ 7 8 "fired" : true, 9 10 "quit" : true 11 12 }); 13 14 } 15 16 Ext.extend(Employee, Ext.util.Observable,{}); 2.绑定相关事件,这里用的事件类本身的引用 TODO 考虑怎么用其他的对象 1 v

【ExtJS】自定义组件datetimefield(一)

目的: ExtJS中提供了下拉日期选择控件Ext.form.field.Date与下拉时间选择控件Ext.form.field.Time.不过没有一个在选择日期时选择时间的控件datetimefield.目的就是运用自定义组件的方法,来扩展下拉日期选择控件Ext.form.field.Date,在下拉框中添加时间选择的组件.目标效果: 第一步:继承Ext.picker.Date,创建My.picker.DateTime类 1 Ext.define('My.picker.DateTime', {

ExtJS 中自定义类

首先我们来看一看在Javascript中,是怎样自定义类的: var Person = function (name, age) { this.Name = ""; this.Age = 0; this.Say = function (msg) { alert(this.Name + " Says : " + msg); } this.init = function (name, age) { this.Name = name; this.Age = age; }

自定义ExtJS插件

http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f73b6f93834c28c3933fc23904564711b2e73a7650598f832b3b57b2111df7f03471360022b791d58c40dcba852858d2616b2e08c31c528516f881007d8037902bfede13f0cdf525e3ddc5a2a84352ba44737f97868d4d7065dd

ExtJs特点、优缺点及注意事项

摘自:ExtJs特点.优缺点及注意事项 1.什么是ExtJs?ExtJS可以用来开发RIA也即富客户端的AJAX应用,是一个用javascript写的,主要用于创建前端用户界面,是一个与后台技术无关的前端Ajax框架.因此,可以把ExtJS用在.Net.Java.Php等各种开发语言开发的应用中.ExtJS的前身来自于YUI,经过不断发展与改进,现在已经成为最完整与成熟的一套构建RIA Web应用的JavaScript基础库.利用ExtJS构建的RIA Web应用具有与桌面程序一样的标准用户界面

使用Ext.define自定义类

ExtJS 允许用户使用Ext.define 自定义类.本文将通过实例介绍如何使用Ext.define自定义类,并介绍ExtJS 的动态加载(Require方法)的使用方法. Javascript自定义类 在Javascript中,自定义类是这样的: // 在Javascript中,自定义类 var Person = function(name, age) { this.Name = ""; this.Age = 0; this.say = function(msg) { alert(

EXTJS 3.0 资料 控件之 Store 用法

最近工作,发现在Extjs中自定义Store的功能挺多,特意在此做笔记,几下来,具体代码如下: 1.定义Store //定义Store var ItemSelectorStore = new Ext.data.ArrayStore({ fields: [ { name: 'BaseInfoId' }, { name: 'Title' } ] }); 2.根据Grid的数据,循环往Store里面插 var rows = grid.getSelectionModel().getSelections(

EXTJS--使用Ext.define自定义类

Javascript自定义类 var person = function(name,age){ this.Name = ""; this.Age = 26: this.Say = function(msg){ alert(this.Name + " Says : " + msg); } this.init = function(name,age){ this.Name = name; this.Age = age; } this.init(name, age); }