论坛首页 Web前端技术论坛

ExtJS3 下拉树TreeComboBox的修改

浏览 10434 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-12-17   最后修改:2009-12-22

先来一个效果图,已在Firefox3.5、IE7、Chrome3中测试正常

完整应用和代码请转到 http://www.iteye.com/topic/553020


 

拜读了[Ext 3.x + Ext 2.x] 下拉树 Ext.ux.ComboBoxTree 学习了不少东西,但和自己现用的TreeComboBox比较还是发现有些地方不妥,这里列出来大家探讨一下

1、xiexueze修改的下拉树每次展开时都会加载一次json,我测试的结果,不知道是不是我配置不当造成

2、tree貌似必须从外部传递进来,而tree在扩展内部实现

3、不是问题的问题,扩展定义了很多默认属性,修改了一些底层的方法

现在提出我的代码,其实也是ExtJS2.0的时候从其他地方学过来的,自己修改了一些代码,具体出处已经忘记了,如大家发现了请指出,谢谢

Ext.namespace("Ext.ux.form");

Ext.ux.form.TreeComboBox = Ext.extend(Ext.form.ComboBox, {

      initComponent : function(ct, position) {
        this.divId = 'tree-' + Ext.id();
        if (isNaN(this.maxHeight))
          this.maxHeight = 200;
        Ext.apply(this, {
              tpl : '<tpl>' + '<div style="height:' + this.maxHeight + 'px;">' + '<div id="' + this.divId + '"></div>' + '</div></tpl>'
            });

        var root = new Ext.tree.AsyncTreeNode({
              text : this.rootText,
              id : this.rootId,
              loader : new Ext.tree.TreeLoader({
                    dataUrl : this.treeUrl,
                    clearOnLoad : true
                  })
            });

        this.tree = new Ext.tree.TreePanel({
              border : false,
              root : root,
              rootVisible : this.rootVisible,
              listeners : {
                scope : this,
                click : function(node) {
                  this.setValue(node);
                  this.collapse();
                }
              }
            });

        Ext.ux.form.TreeComboBox.superclass.initComponent.call(this);
      },

      onRender : function(ct, position) {
        Ext.ux.form.TreeComboBox.superclass.onRender.call(this, ct, position);

        this.on("expand", function() {
              if (!this.tree.rendered) {
                this.tree.render(this.divId);
              }
            }, this)

      },

      /*以下代码是为了将tree的node设置到combo中 因为我还有一些其他的作用,所以我是将这部分的代码重写到其他地方了
      setValue : function(node) {
        if (typeof node == "object") {
          this.setRawValue(node.text);
          if (this.hiddenField) {
            this.hiddenField.value = node.id;
          }
        } else {
          this.setRawValue(node);
        }
      }
      */

    });

Ext.reg('uxtreecombobox', Ext.ux.form.TreeComboBox);

 之前的setValue我是直接覆盖了combo的方法

Ext.override(Ext.form.ComboBox, {
      setValue : function(node) {
        if (typeof node == "object") {
          // 当node为object对象时 node和tree里面的对应
          this.lastSelectionText = node.text;
          // 设置显示文本为node的text
          this.setRawValue(node.text);
          if (this.hiddenField) {
            // 设置隐藏值为node的id
            this.hiddenField.value = node.id;
          }
          this.value = node.id;
          return this;
        } else {
          // 当node为文本时 这段代码是从combo的源码中拷贝过来的 具体作用不细说了
          var text = node;
          if (this.valueField) {
            var r = this.findRecord(this.valueField, node);
            if (r) {
              text = r.data[this.displayField];
            } else if (Ext.isDefined(this.valueNotFoundText)) {
              text = this.valueNotFoundText;
            }
          }
          this.lastSelectionText = text;
          if (this.hiddenField) {
            this.hiddenField.value = node;
          }
          Ext.form.ComboBox.superclass.setValue.call(this, text);
          this.value = node;
          return this;
        }
      }
    })

 为什么要重写这个方法,请参考Ext.form.ComboBox加载json时刻默认选中的 ...

下面是使用的代码

xtype : 'uxtreecombobox',
id : 'Ext.Strong.tyh.combo.yhBmid',
hiddenName : 'yhBmid',
fieldLabel : '${action.getText("YH_BM")}',
editable : false,
shadow : true,
maxHeight : 200,
mode : 'local',
displayField : 'text',
valueField : 'id',
triggerAction : 'all',
allowBlank : false,
treeUrl : '<@s.url action="tbm_Shu_XianShi!json"/>',
rootText : 'root',
rootId : '0',
// api里面的意思是
//【true to restrict the selected value to one of the values in the list, false to allow the user to set arbitrary text into the field (defaults to false)】
// 我的理解是combo中设置的值
// 能否为不在store中的内容
// 因为如果默认设置为false的时候每次在失去该combo对象的焦点时刻会触发一个事件重新设置一下value
// 这个问题我解决了好久才搞定
forceSelection : true,
rootVisible : false
 

为什么forceSelection : true,我们看一下源代码

    beforeBlur : function(){
        var val = this.getRawValue(),
            rec = this.findRecord(this.displayField, val);
        // 注意这里 如果rec不存在且forceSelection为true
        if(!rec && this.forceSelection){
            if(val.length > 0 && val != this.emptyText){
                this.el.dom.value = Ext.isDefined(this.lastSelectionText) ? this.lastSelectionText : '';
                this.applyEmptyText();
            }else{
                this.clearValue();
            }
        }else{
            if(rec){
                val = rec.get(this.valueField || this.displayField);
            }
            this.setValue(val);
        }
    },

 总结一下,ExtJS的确实存在很多陷阱,很多简单的应用都必须从底层去解决,但是也提供了很好的学习机会,ExtJS的代码很多地方都值得我们去认真学习

  • 大小: 37.3 KB
   发表时间:2010-09-02  
this.on("expand", function() {
            alert(this.tree.rendered)
            if (!this.tree.rendered) {
                this.tree.render(this.divId);
            }
        }, this)

造成数据延迟,当forceSelection: true时会出问题,因为没有展示的下拉数据,是无法选中某项的
0 请登录后投票
   发表时间:2010-09-02  
不加上this.store = new Ext.data.SimpleStore({ fields: [], data: [[]] });就会出错的
0 请登录后投票
   发表时间:2010-09-02  
不知道楼主是什么版本的EXT,本人是3.2的
0 请登录后投票
   发表时间:2010-09-02  
用继承ComboBox么?很多方法不合适吧~继承TriggerField就OK了
0 请登录后投票
   发表时间:2010-09-02  
TriggerField  也不行吧。。还是没有好的解决方法,楼主不在
0 请登录后投票
论坛首页 Web前端技术版

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