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,
});
这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?
这个问题可以忽略了,还有个问题想请教下:
如果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,否则会报错。
这个问题你有别的办法解决吗?
我的解决办法是在构造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,否则会报错。
这个问题你有别的办法解决吗?
这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?
这个。。还没有考虑
,因为才开始使用ExtJs没多久,很多应用细节还没机会去尝试。我觉得你的方法也挺好了,添加“清空”的同时顺便再加上一个“刷新”树节点的控制都不错。
在我贴代码之后又做了一些修改,但是修改后没有及时更新上来,太多事情要处理了啊。。。
你说的通过getValue()取不到值的问题,很可能是之后解决的,不用getNodeValue().id那么麻烦。。。,另外,异步发送请求的方法cu.get(...).done(...)只是对Ext.ajax.request做了简单的封装,并且添加了全局的异常处理而已。这种写法是从jquery里学过来的,我还摆脱不了一些jquery的使用习惯。
getValue()方法只是简单地返回this.value,关键是doSetValue()方法中对value的设置。现在是不是可以取到正确的值了?如果是就应该是之前的doSetValue()方法有问题,具体修改了什么地方我想不起来了。。。太久了。。
ExtJs 3 自定义combotree的更多相关文章
- 【ExtJS】自定义组件datetimefield(二)
接上[ExtJS]自定义组件datetimefield(一) 第三步:添加按钮事件绑定,获取选定的时间 privates:{ finishRenderChildren: function () { v ...
- ExtJS 中自定义类
首先我们来看一看在Javascript中,是怎样自定义类的: var Person = function (name, age) { this.Name = ""; this.Ag ...
- 【ExtJS】自定义组件datetimefield(一)
目的: ExtJS中提供了下拉日期选择控件Ext.form.field.Date与下拉时间选择控件Ext.form.field.Time.不过没有一个在选择日期时选择时间的控件datetimefiel ...
- Extjs中自定义事件
//Ext中所谓的响应事件,响应的主要是组件中已经定义的事件(通过看api各组件的events可以找到) //主要作用就是利用on调用各组件的事件处理函数,然后在函数中作用户想要的操作 ...
- Extjs 学习总结-Ext.define自定义类
本教程整理了extjs的一些基本概念及其使用,包括自定义类(Ext.define).数据模型.代理等.本节介绍使用Ext.define自定义类 使用Ext.define自定义类 1. 首先看看js中自 ...
- ExtJS学习(一)Ext自定义类实现
工作中项目需要extjs,所以学习一下,做个笔记防止遗忘了.以后回忆起来也方便. 首先下载extjs官网地址:http://extjs.org.cn/ 下载以后的目录结构: 先写一个入门的程序吧自定义 ...
- ExtJS 4.2 教程-03:使用Ext.define自定义类
转载自起飞网,原文地址:http://www.qeefee.com/extjs-course-3-define-classes ExtJS 4.2 教程-01:Hello ExtJS ExtJS 4. ...
- ExtJs特点、优缺点及注意事项
摘自:ExtJs特点.优缺点及注意事项 1.什么是ExtJs?ExtJS可以用来开发RIA也即富客户端的AJAX应用,是一个用javascript写的,主要用于创建前端用户界面,是一个与后台技术无关的 ...
- EXTJS 4.2 资料 控件之 Store 用法
最近工作,发现在Extjs中自定义Store的功能挺多,特意在此做笔记,几下来,具体代码如下: 1.定义Store //定义Store var ItemSelectorStore = new Ext. ...
随机推荐
- 016 sleep,wait,yield,join区别
1.线程通常有五种状态,创建,就绪,运行.阻塞和死亡状态.2.阻塞的情况又分为三种:(1).等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中.进入 ...
- openjudge-NOI 2.6-1775 采药
题目链接:http://noi.openjudge.cn/ch0206/1775/ 题解: 很经典的01背包问题,设时间为t,价值为v 一维压缩,状态转移方程fj=max(fj,fj-ti+vi) # ...
- Windows下Oracle数据库自动备份批处理脚本
expdb命令版本 @echo off REM ########################################################### REM # Windows Se ...
- ECMA-Script5
严格模式 所谓严格模式,从字面上就很好理解,即更严格的模式 在这种模式下执行,浏览器会对JS的要求更苛刻. 举例: function m1(){ max = 100; } m1(); al ...
- ***PHP5.6.x SSL3_GET_SERVER_CERTIFICATE:certificate verify failed 解决方案
centos: 在php.ini中增加一行 1 openssl.cafile=/etc/pki/tls/certs/ca-bundle.crt 重启服务器使修改生效
- 【重点】Jmeter----- 将 JDBC Request 查询结果作为下一个接口参数方法(二)
一.说明 jmeter与数据库mysql已连接成功 二.需求 1.前置条件: 1.已user数据库的前8位手机号码作为行动计划的名称 2.行动计划的日期是2018-10-17 2.操作步骤: 1)获取 ...
- TPC-H数据导入MySQL教程
0. TPC-H是啥 TPC-H是TPC提供的一个benchmark,用来模拟一个现实中的商业应用,可以生成一堆虚构的数据,且自带一些查询,可以导入到各种数据库中来模拟现实需求,检查性能. 具体是怎样 ...
- 关于JS中判断是数字和小数的正则表达式用法
关于JS中判断是数字和小数的正则表达式用法 正则表达式 正则表达式是由一个字符序列形成的搜索模式. 当你在文本中搜索数据时,你可以用搜索模式来描述你要查询的内容. 正则表达式可以是一个简单的字符,或一 ...
- loadrunner乱码问题解决办法
7.LoadRunner回放脚本时,在浏览器显示的中文是乱码 最近,遇到了好多乱码的问题,解决了一些,还有最后一个乱码,能想到的各种办法都试过了,还是不行,很奇怪啊. 解决这些乱码时,涉及到了http ...
- LoadRunner 使用虚拟IP测试流程
LoadRunner 使用虚拟IP测试流程 LoadRunner 使用IP欺骗的原因 . 当某个IP的访问过于频繁,或者访问量过大是,服务器会拒绝访问请求,这时候通过IP欺骗可以增加访问频率和访问量, ...