最近为了实现一个属性下拉框被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',
    maxHeight: 400,
    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,
            maxHeight: this.maxHeight,
            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: 'your url of json',
//emptyText: '请选择所属组织',
allowBlank: false
});

效果图:

Ext.form.field.ComboBoxView source...

Ext5实现树形下拉框ComboBoxTree的更多相关文章

  1. easyui源码翻译1.32--ComboTree(树形下拉框)

    前言 扩展自$.fn.combo.defaults和$.fn.tree.defaults.使用$.fn.combotree.defaults重写默认值对象.下载该插件翻译源码 树形下拉框结合选择控件和 ...

  2. Vue实现树形下拉框

    Vue自身并没有实现树形下拉框的组件,找了很多资料,最后在Github上找了个插件vue-treeselect,功能还是比较全的,模糊搜索.多选.延迟加载.异步搜索.排序,自定义.Vuex支持等等.这 ...

  3. 雷林鹏分享:jQuery EasyUI 表单 - 创建树形下拉框

    jQuery EasyUI 表单 - 创建树形下拉框 树形下拉框(ComboTree)是一个带有下列树形结构(Tree)的下拉框(ComboBox).它可以作为一个表单字段进行使用,可以提交给远程服务 ...

  4. Dorado开发——树形下拉框

    最近在学习Dorado开发的过程中,遇到了一个问题,Dorado的树形下拉框选择:Dorado默认情况下父节点和子节点都是可选的,而我要实现的是父节点不可选. 解决办法:在下拉框中,判断父子节点,点击 ...

  5. 树形下拉框ztree、获取ztree所有父节点,ztree的相关方法

    参考:jQuery树形控件zTree使用小结 需求 添加.修改的终端需要选择组织,组织是多级架构(树状图显示). 思路 1.因为下拉框需要树状图显示,所以排除使用select做下拉框,改用input  ...

  6. easyui-conbotree树形下拉框。。。转

    最近一直在研究这个树形的下拉选择框,感觉非常的有用,现在整理下来供大家使用: 首先数据库的表架构设计和三级菜单联动的表结构是一样,(父子关系) 1.下面我们用hibernate建一下对应的额实体类: ...

  7. vue 树形下拉框 亲测 好用

    https://vue-treeselect.js.org/ 顺带说一个开发中使用这个组件遇到的问题,关于回显之后无法修改的问题  找了很长时间 原因是数据类型导致的问题,数组里面应该是数字类型,直接 ...

  8. EasyUI:combotree(树形下拉框)复选框选中父节点(子节点的状态也全部选中)输入框中只显示父节点的文本值

    参考: https://blog.csdn.net/weixin_43236850/article/details/100320564

  9. ligerui多选动态下拉框

    今天下午要求做一个支持多选的,并且插件用ligerui的,当时有点小懵了,因为没用过ligerui啊!而且按照API的介绍,我做得也很好啊,可是为什么就是显示不出来?据说有位小神比较厉害,请教来之,两 ...

随机推荐

  1. vmware centos nat模式下连不上网络解决办法

    简单来讲,当你创建一台虚拟机时,VMware为你虚拟了三种接入网络的方式:桥连接,NAT,使用主机网络,Vmware 10中默认对应 VMnet0,VMnet1,VMnet8 .    当选择桥连接方 ...

  2. neXtep 安装过程整理

    1 授权root用户远程登录 2  文件下载 http://www.nextep-softwares.com/ 选择DOWNLOAD NOW 选择你需要的版本 我选择的版本是 neXtep.1.0.7 ...

  3. Angular通过CORS实现跨域方案

    以前有一篇很老的文章网上转了很多,包括现在如果你百度"跨域"这个关键字,前几个推荐的都是"Javascript跨域总结与解决方案".看了一下感觉手段有点陈旧了, ...

  4. ARM 开发工具 Keil和DS-5的比较。

    http://www.eeboard.com/bbs/thread-25219-1-1.html 如今ARM体系架构的处理器在嵌入式市场上呼风唤雨,从低端的MCU应用到高端的多媒体消费电子,移动设备领 ...

  5. 探索模拟angular的双向绑定

    前言 本次探索的demo是基于jquery写的,毕竟jquery提供了强大的选择器,用惯了就离不开它了!angular的双向绑定实在是有点精深,本次探索只实现了文本的双向绑定. View-Model ...

  6. c语言第12次作业

    #include<stdio.h> struct student { ]; ]; ]; double grade; }; void main() { ]; ;i<;i++) { pr ...

  7. jQuery插件的开发之$.extend(),与$.fn.extend()

        jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery命名空间的函数,另一种 ...

  8. EditPlus 3.7.1186 中文版(10月27日更新)重大性能改进,推荐更新!

    3.7.* 版的 EditPlus 存在性能问题:加载行数比较多的文档时,要等很长的时间.加载一个十几兆的文本文件,可能需要等十几秒.在编辑窗口内翻页也会有明显的迟滞感.而此前的 3.6 版本并非如此 ...

  9. Ubuntu/linux 有关权限修改的命令

    chmod更改文件权限命令 最常用的基础命令chmod chmod 777  目录名(路径名) 777 三位数字分别代表 user.group.others 的权限,可读(r).可写(w).可执行(x ...

  10. 读取Devexpress内部的图标

    1.图标在Dev源码的存储路径: Sources D.x.u 15.1.3\DevExpress.Images\Images   2.引用DevExpress.Images.v15.1.dll文件,代 ...