当前位置: 代码迷 >> JavaScript >> ExtJS中树形构造级联选中(三态)
  详细解决方案

ExtJS中树形构造级联选中(三态)

热度:125   发布时间:2012-07-26 12:01:08.0
ExtJS中树形结构级联选中(三态)
在使用ExtJS进行开发时,常常遇到需要用到树形结构Ext.tree.TreePanel,而且经常需要对TreePanel进行级联选中与取消选中,我们的做法无非就是监听checkchange事件进行相应的处理,常用的写法是:
var treePanel = new Ext.tree.TreePanel({
...
listeners : {
'checkchange' : function(){
...
}
}
});

这样做可行吗,答案是肯定的,肯定是可以实现的,只是当你需要多个地方都需要进行级联选中时,你需要拷贝这些代码到需要的地方,这样写代码有些糟糕,复用性太低,也不易于维护,同时,这样写不是很好实现checkbox的三种状态,于是动手写了这样一个插件,实现了树形结构的级联选中与三态,代码如下:
/* 带有CheckBox的树的选中的插件
 * author:jn_nian
 * createTime:2010-10-24 21:46
 * usage: Ext3使用 plugins : ['treecheck']或plugins:[new Ext.ux.TreePanelCheck()]
 * Ext2使用 :plugins:[new Ext.ux.TreePanelCheck()]
*******************************************************************/
 
 Ext.ux.TreePanelCheck = Ext.extend(Ext.tree.TreePanel,{
 	init : function(treePanel){
 		var rootNode = treePanel.getRootNode();
 		
 		treePanel.on('expandnode',this.doLazyCheck,rootNode);
 		treePanel.on('checkchange',this.handlerCheck,this);
 	},
 	
 	
 	//检查子结点选中的情况
 	doChildHasChecked : function(node){
 		var childNodes = node.childNodes;
		var checkedNum = 0;
		if(childNodes || childNodes.length>0){
			for(var i=0;i<childNodes.length;i++){
				if(childNodes[i].getUI().checkbox.checked){
    				checkedNum = checkedNum + 1;
				}
			}
		}
		return checkedNum;
 	},
 	
 	//父节点选中
 	doParentCheck : function(node ,checked){
 		var checkbox = node.getUI().checkbox;
		if(typeof checkbox == 'undefined') return false;
		node.getUI().checkbox.indeterminate = false;
		node.getUI().checkbox.checked = checked;
		
		node.attributes.checked = checked;
		var childChecked = this.doChildHasChecked(node);
		if(childChecked == node.childNodes.length){
			node.getUI().checkbox.checked = true;
			node.getUI().checkbox.indeterminate = false;
		}else if(childChecked == 0){
			var indeterminate = false;
			node.eachChild(function(child){     
	        	if(child.getUI().checkbox.indeterminate){
	        		indeterminate = true;
	        		return false;
	        	}
	        }); 
			node.getUI().checkbox.checked = false;
			node.getUI().checkbox.indeterminate = indeterminate;
		}else{
			node.getUI().checkbox.checked = false;
			node.getUI().checkbox.indeterminate = true; //半选中状态
		}
		
		node.getOwnerTree().fireEvent('check', node, checked);
		var parentNode = node.parentNode;
		if( parentNode !== null){
			this.doParentCheck(parentNode,checked);
		}
 	},
 	
 	handlerCheck : function(node,checked){
 		var parentNode = node.parentNode;
        if(!Ext.isEmpty(parentNode)) {   
        	this.doParentCheck(parentNode,checked);   
        }
        node.attributes.checked = checked;
//		node.expandChildNodes(true);
        node.eachChild(function(child){     
        	child.ui.toggleCheck(checked);    
            child.attributes.checked = checked;     
            child.fireEvent('checkchange', child, checked);
        });
 	},
 	
 	//延迟加载选中
 	doLazyCheck : function(node){
 		if(!Ext.isEmpty(node.parentNode)){
			var nodeChecked = node.getUI().checkbox.checked;
			//node.expandChildNodes(true);
			node.eachChild(function(child){
				child.getUI().checkbox.checked = nodeChecked;
			});
		}
 	},
 	
 	getPType : function(){
 		return this.ptype;
 	}
 });
 Ext.preg('treecheck',Ext.ux.TreePanelCheck);

此代码可以在Ext2.x与3.x下正常运行,当你使用Ext3.x时你不需要对此代码作任何改动,当你使用Ext2.x时,请注释掉最后一行代码:Ext.preg('treecheck',Ext.ux.TreePanelCheck);
最终实现效果图如附件中所示
1 楼 tkl211 2012-05-30  
我用这个插件出现这个问题。
比如我 三级菜单
10001
    10002
         10003
         10004
(1)我选中 10001的时候,这时候级联选中子节点是没问题,我后台获取id也是这四个,但是当我取消 10003的时候, 这时候取得的checked值 只有 10004 这一个,而10001,10002这时候应该处于半选中状态,应该也能取得值才对的,但是去无法取到值。
(2)我初始化的时候, 10001,10002,10003的checked 是true,10004的为false,这时候,会把我10004这个也默认选中的。
2 楼 jn_nian 2012-06-03  
tkl211 写道
我用这个插件出现这个问题。
比如我 三级菜单
10001
    10002
         10003
         10004
(1)我选中 10001的时候,这时候级联选中子节点是没问题,我后台获取id也是这四个,但是当我取消 10003的时候, 这时候取得的checked值 只有 10004 这一个,而10001,10002这时候应该处于半选中状态,应该也能取得值才对的,但是去无法取到值。
(2)我初始化的时候, 10001,10002,10003的checked 是true,10004的为false,这时候,会把我10004这个也默认选中的。

tkl211 写道
我用这个插件出现这个问题。
比如我 三级菜单
10001
    10002
         10003
         10004
(1)我选中 10001的时候,这时候级联选中子节点是没问题,我后台获取id也是这四个,但是当我取消 10003的时候, 这时候取得的checked值 只有 10004 这一个,而10001,10002这时候应该处于半选中状态,应该也能取得值才对的,但是去无法取到值。
(2)我初始化的时候, 10001,10002,10003的checked 是true,10004的为false,这时候,会把我10004这个也默认选中的。

你好,我在做这个插件的时候,认定半选中状态的不算选中的,可能查询Ext源码中getChecked方法的源代码,对其重写即可解决,只需要多加上一个判断,如果有问题,请留言
3 楼 tkl211 2012-06-04  
好的,谢谢。。。 我这两天没上网,晚上我看一下呢。。
  相关解决方案