你的位置:首页 > Java教程

[Java教程]Ext5实现树形下拉框ComboxTree


最近为了实现一个属性下拉框被Ext框架折腾了好几天。。 

所以,首先要说的是,不管你要做什么系统、强烈建议你不要选择Ext。据我这几天的搜索,应该这个框架现在用的人也很少了。

Ext框架的缺陷:框架沉重、扩展性差(与其他js框架相比)、各版本差别大(Ext3、4、5不兼容)。

现在进入正题,这几天研究ext实现树形下拉框发现网上常见的两种做法:

1、扩展Ext.form.field.ComboBox

  使用这种方式的好处是ComboBox与我们要实现的东西其行为更为相似,在取值、赋值方面比较方便、可以对触发下拉事件上做定制。

  最后实现的东西发现浏览器不能兼容、只有Win10的Edge可以完美呈现,无奈放弃。。

2、扩展Ext.form.field.Picker

  上一条路没有走通最终选择了这种方式。这种方式的好处:对树形节点的展开、关闭不会影响到用户的选取操作。

 

这段代码也是根据网络上的源码做了修改,之所以发出来因为网上实在是找不到基于Ext5的实现。所以我判断现在使用Ext框架的人应该极少了,网上有的都是几年前使用Ext4、3的人发表的。所有基于Ext4的实现在Ext5上都不能完美支持。。

 

定义组件:

Ext.define('Ext.ux.ComboBoxTree', {  extend: 'Ext.form.field.Picker',  requires: ['Ext.tree.Panel'],  alias: ['widget.comboboxtree'],  multiSelect: false,  multiCascade: true,  rootVisible: false,  displayField: 'text',  emptyText:'',  submitValue: '',  url:'',  pathValue: '',  defaultValue: null,  pathArray: [],  selectNodeModel: 'all',  setValue: function (value) {    if (value) {//注意:此处的判断会使id为0的值选中失效      if (typeof value == 'number') {        this.defaultValue = value;      }      this.callParent(arguments);    }  },  initComponent: function () {    var self = this;    self.selectNodeModel = Ext.isEmpty(self.selectNodeModel) ? 'all' : self.selectNodeModel;    Ext.apply(self, {      fieldLabel: self.fieldLabel,      labelWidth: self.labelWidth    });    self.store = Ext.create('Ext.data.TreeStore', {      root: { expanded: true },      proxy: { type: 'ajax', url: self.url },      autoLoad: true    });    self.store.addListener('load', function (st, rds, opts) {      if (self.defaultValue) {        var defaultRecord = self.store.getNodeById(self.defaultValue);        self.setDefaultValue(defaultRecord.get('id'), defaultRecord.get('text'));      } else {        self.setDefaultValue('', self.emptyText);      }    });    self.callParent();  },  createPicker: function () {    var self = this;    self.picker = Ext.create('Ext.tree.Panel', {      //height: self.treeHeight == null ? 200 : self.treeHeight,      autoScroll: true,      floating: true,      focusOnToFront: false,      shadow: true,      ownerCt: this.ownerCt,      useArrows: false,      store: this.store,      rootVisible: this.rootVisible,      displayField: this.displayField,      viewConfig: {        onCheckboxChange: function (e, t) {          if (self.multiSelect) {            var item = e.getTarget(this.getItemSelector(), this.getTargetEl()),              record;            if (item) {              record = this.getRecord(item);              var check = !record.get('checked');              record.set('checked', check);              if (self.multiCascade) {                if (check) {                  record.bubble(function (parentNode) {                    if ('Root' != parentNode.get('text')) {                      parentNode.set('checked', true);                    }                  });                  record.cascadeBy(function (node) {                    node.set('checked', true);                    node.expand(true);                  });                } else {                  record.cascadeBy(function (node) {                    node.set('checked', false);                  });                  record.bubble(function (parentNode) {                    if ('Root' != parentNode.get('text')) {                      var flag = true;                      for (var i = 0; i < parentNode.childNodes.length; i++) {                        var child = parentNode.childNodes[i];                        if (child.get('checked')) {                          flag = false;                          continue;                        }                      }                      if (flag) {                        parentNode.set('checked', false);                      }                    }                  });                }              }            }            var records = self.picker.getView().getChecked(),              names = [],              values = [];            Ext.Array.each(records, function (rec) {              names.push(rec.get('text'));              values.push(rec.get('id'));            });            self.submitValue = values.join(',');            self.setValue(names.join(','));          }        }      }    });    self.picker.on({      itemclick: function (view, recore, item, index, e, object) {        var selModel = self.selectNodeModel;        var isLeaf = recore.data.leaf;        var isRoot = recore.data.root;        var view = self.picker.getView();        if (!self.multiSelect) {          if ((isRoot) && selModel != 'all') {            return;          } else if (selModel == 'exceptRoot' && isRoot) {            return;          } else if (selModel == 'folder' && isLeaf) {            return;          } else if (selModel == 'leaf' && !isLeaf) {            var expand = recore.get('expanded');            if (expand) {              view.collapse(recore);            } else {              view.expand(recore);            }            return;          }          self.submitValue = recore.get('id');          self.setValue(recore.get('text'));          self.eleJson = Ext.encode(recore.raw);          self.collapse();        }      }    });    return self.picker;  },  listeners: {    expand: function (field, eOpts) {      var picker = this.getPicker();      if (!this.multiSelect) {        if (this.pathValue != '') {          picker.expandPath(this.pathValue, 'id', '/', function (bSucess, oLastNode) {            picker.getSelectionModel().select(oLastNode);          });        }      } else {        if (this.pathArray.length > 0) {          for (var m = 0; m < this.pathArray.length; m++) {            picker.expandPath(this.pathArray[m], 'id', '/', function (bSucess, oLastNode) {              oLastNode.set('checked', true);            });          }        }      }    }  },  clearValue: function () {    this.setDefaultValue('', '');  },  getEleJson: function () {    if (this.eleJson == undefined) {      this.eleJson = [];    }    return this.eleJson;  },  getSubmitValue: function () {    if (this.submitValue == undefined) {      this.submitValue = '';    }    return this.submitValue;  },  getDisplayValue: function () {    if (this.value == undefined) {      this.value = '';    }    return this.value;  },  getValue: function () {    return this.getSubmitValue();  },  setPathValue: function (pathValue) {    this.pathValue = pathValue;  },  setPathArray: function (pathArray) {    this.pathArray = pathArray;  },  setDefaultValue: function (submitValue, displayValue) {    this.submitValue = submitValue;    this.setValue(displayValue);    this.eleJson = undefined;    this.pathArray = [];  },  alignPicker: function () {    var me = this,      picker,      isAbove,      aboveSfx = '-above';    if (this.isExpanded) {      picker = me.getPicker();      if (me.matchFieldWidth) {        picker.setWidth(me.bodyEl.getWidth());      }      if (picker.isFloating()) {        picker.alignTo(me.inputEl, "", me.pickerOffset); // ""->tl        isAbove = picker.el.getY() < me.inputEl.getY();        me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);        picker.el[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);      }    }  }});

以上代码有待优化,由于只用了单选,所以多选应该还有点问题。

调用代码:

Ext.create('Ext.ux.ComboBoxTree', {        cId: 'cbOrganizationId',        name: 'OrganizationId',        fieldLabel: '所属组织',        editable: false,        url: urls.SaleInfo.GetOrganizationTree,        //emptyText: '请选择所属组织',        allowBlank: false      });

 

 

 

Ext.form.field.ComboBoxView source...