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的更多相关文章

  1. 【ExtJS】自定义组件datetimefield(二)

    接上[ExtJS]自定义组件datetimefield(一) 第三步:添加按钮事件绑定,获取选定的时间 privates:{ finishRenderChildren: function () { v ...

  2. ExtJS 中自定义类

    首先我们来看一看在Javascript中,是怎样自定义类的: var Person = function (name, age) { this.Name = ""; this.Ag ...

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

    目的: ExtJS中提供了下拉日期选择控件Ext.form.field.Date与下拉时间选择控件Ext.form.field.Time.不过没有一个在选择日期时选择时间的控件datetimefiel ...

  4. Extjs中自定义事件

    //Ext中所谓的响应事件,响应的主要是组件中已经定义的事件(通过看api各组件的events可以找到)         //主要作用就是利用on调用各组件的事件处理函数,然后在函数中作用户想要的操作 ...

  5. Extjs 学习总结-Ext.define自定义类

    本教程整理了extjs的一些基本概念及其使用,包括自定义类(Ext.define).数据模型.代理等.本节介绍使用Ext.define自定义类 使用Ext.define自定义类 1. 首先看看js中自 ...

  6. ExtJS学习(一)Ext自定义类实现

    工作中项目需要extjs,所以学习一下,做个笔记防止遗忘了.以后回忆起来也方便. 首先下载extjs官网地址:http://extjs.org.cn/ 下载以后的目录结构: 先写一个入门的程序吧自定义 ...

  7. ExtJS 4.2 教程-03:使用Ext.define自定义类

    转载自起飞网,原文地址:http://www.qeefee.com/extjs-course-3-define-classes ExtJS 4.2 教程-01:Hello ExtJS ExtJS 4. ...

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

    摘自:ExtJs特点.优缺点及注意事项 1.什么是ExtJs?ExtJS可以用来开发RIA也即富客户端的AJAX应用,是一个用javascript写的,主要用于创建前端用户界面,是一个与后台技术无关的 ...

  9. EXTJS 4.2 资料 控件之 Store 用法

    最近工作,发现在Extjs中自定义Store的功能挺多,特意在此做笔记,几下来,具体代码如下: 1.定义Store //定义Store var ItemSelectorStore = new Ext. ...

随机推荐

  1. USB各种模式 解释

    1.MTP: 通过MTP这种技术,可以把音乐传到手机里.有了U盘功能为什么还要多此一举呢?因为版权问题,MTP可以把权限文件从电脑上导过去:如果只使用手机的U盘功能,把歌的文件拷过去之后,没有权限文件 ...

  2. MAC和PHY的区别 (转自http://www.cnblogs.com/feitian629/archive/2013/01/25/2876857.html)

    一块以太网网卡包括OSI(开方系统互联)模型的两个层.物理层和数据链路层.物理层定义了数据传送与接收所需要的电与光信号.线路状态.时钟基准.数据编码和电路等,并向数据链路层设备提供标准接口.数据链路层 ...

  3. linux的curl用法【转】

    每分钟访问云签到任务执行页面.顺便记录了下curl的用法.以下内容摘自阮一峰博客. 一.查看网页源码 直接在curl命令后加上网址,就可以看到网页源码.我们以网址www.sina.com为例(选择该网 ...

  4. eclipse 常见问题之字体更改、添加注释模板

    有些同学可能会和我有一样的困扰,每次想要更改字体大小.背景颜色等,都需要百度一下才知道怎么去做...不知道有没有这种情况的孩子,反正我经常遇到,老是记不住,今天写下来,顺带自己忘记的时候可以查看一下. ...

  5. 20180830 安装git时报错,

    安装:https://blog.csdn.net/u013256816/article/details/54743470 解决问题:https://blog.csdn.net/daojibruce/a ...

  6. java版云笔记(二)

    云笔记 基本的环境搭建好了,今天做些什么呢,第一是链接数据库(即搭建Spring-Batistas环境),第二是登录预注册. 注:这个项目的sql文件,需求文档,需要的html文件,jar包都可以去下 ...

  7. 关于JavaScript中实现继承,及prototype属性

    感谢Mozilla 让我弄懂继承. JavaScript有八种基本类型,函数属于object.所以所有函数都继承自object.//扩展:对象,基本上 JavaScript 里的任何东西都是对象,而且 ...

  8. 转- 阿里云、Amazon、Google云数据库方案架构与技术分析

    「一切都会运行在云端」. 云时代早已来临,本文着眼于顶级云服务商云服务商的云数据库方案背后的架构,以及笔者最近观察到的一些对于云数据库有意义的工业界的相关技术的进展,希望读者能有所收获. 现在越来越多 ...

  9. Effective C++学习进阶版

    记得前段时间又一次拿起<Effective C++>的时候,有种豁然开朗的感觉,所以翻出了我第一遍读时做的笔记.只做参考以及查阅之用.如有需要请参阅<Effective C++> ...

  10. 前端代码编辑器ace 语法验证

    本文主要是介绍实际项目中如何加入语法检测功能.官方文档链接https://github.com/ajaxorg/ace/wiki/Syntax-validation 代码编辑器ace,使用webwor ...