zoukankan      html  css  js  c++  java
  • Ext5实现树形下拉框ComboBoxTree

    最近为了实现一个属性下拉框被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...

  • 相关阅读:
    二叉树的深度(剑指offer)
    平衡二叉树(剑指offer)
    平衡二叉树
    513. Find Bottom Left Tree Value(得到左下角的节点)(树的层次遍历)
    637. Average of Levels in Binary Tree(一棵树每层节点的平均数)(二叉树的层序遍历)
    145. Binary Tree Postorder Traversal(非递归实现二叉树的后序遍历)
    正则表达式式总结
    re模块
    生成器 生成器函数 列表推倒式 生成器表达式
    闭包,迭代器
  • 原文地址:https://www.cnblogs.com/hhq365/p/5585245.html
Copyright © 2011-2022 走看看