ComboBox在下拉列表中显示一棵树

时间:2012-06-12 10:25:47

标签: javascript combobox treeview dojo

我想编写一个ComboBox,让用户输入一个查询,同时让他从树中选择一个值。我尝试过编写树选择,但是如果我将代码更改为继承自dijit.form.ComboBox而不是dijit.form.Select,则代码会中断。

这是我选择树的树:

dojo.declare('TreeSelect',dijit.form.Select,{
    constructor: function(widgetArgs){
        this.tree = widgetArgs.tree || new FC_Tree();
        this.initTree = widgetArgs.initTree;
        if(dojo.isFunction(this.initTree))
            this.initTree();
    },
    postCreate: function(){
        this.inherited(arguments);
        this.option = {label: '', value: 'NoValue'};
        this.tree.option = this.option;
        this.addOption(this.option);

        dojo.connect(this.tree,'onClick',this,'closeDropDown');

        dojo.connect(this.tree,'itemSelected',this,'selectOption');
    },
    selectOption: function(opt){
        this.option.label = opt.label || opt;
        this.option.value = opt.value || opt;
        this.option.id = opt.id || opt;
        this.set('value',this.option);                      
    },
    _getMenuItemForOption: function (option){
        return this.tree;
    },
    openDropDown: function(){
        this.tree.refresh();
        this.inherited(arguments);
    },
    clear: function(){
        this.tree.clear();
        this.tree.option.value = '';
        this.tree.option.label = '';
        this.tree.option.id = '';
        this.set('value',this.tree.option);
    },

    initializeTree: function(treeData) {
        // Init the tree only if needed
        dojo.forEach(treeData, function(field) {
            var store = this.tree.model.store;
            store.newItem(field);
        }, this);

    },
    setOpenCallback: function(callback){
        this.tree.setOpenCallback(callback);
    },
    resetTree: function() {
        var store = this.tree.model.store;
        store.fetch( { query: { id: "*" },  
            onItem: function(item) {
                store.deleteItem(item);
            }
        });
    }
});

我曾尝试用这样替换组合框的代码:

dojo.declare('TreeSelect',dijit.form.ComboBox,{

请帮我纠正。 提前谢谢!

添加FC_Tree的代码:

dojo.declare('FC_Tree',dijit.Tree,{
    showRoot: false,
    openOnClick: true,
    noIconForNode: true,
    noMarginForNode: true,
    persist: false,
    openCallback: null,
    constructor: function(){
        if(dojo.isUndefined(arguments[0]) || dojo.isUndefined(arguments[0].model))
        {
            var forest_store = new FC_DataStore({id: 'id', label: 'label'});
            this._storeloaded = false;
            dojo.connect(forest_store,'loaded',this,function(){this._storeloaded = true;})
            this.model = new dijit.tree.ForestStoreModel({store:forest_store});
        }
    },

    setOpenCallback: function(callback){
        this.openCallback = callback;
    },

    option: {},
    itemSelected: function(item){
    },

    onClick: function(item, node, evt){
        var store = this.model.store;
        get = function(){
            return store.getValue(item, "isDir");
        };
        // on folder click mark it unselectable
        if(get("isDir")) 
        {
            this.isExpanded = true;
            this.isExpandable = true;

        }
        else
        {   //In case the item has 'onClick' delegate execute it and assign the output to 'selItem'
            var selItem = (item.onClick && item.onClick[0])? item.onClick[0](this.model.store,item.parentID[0]):item.id[0]; 

            this.option.id = item.id;
            this.option.value = item.value;
            this.option.label = item.label;
            this.itemSelected(this.option);

        }
    },

    onOpen: function(item, node){
        if(this.rootNode.item == item){
            return this.inherited(arguments);
        }

        var data = (this.openCallback != null) ? this.openCallback(item, node) : {};
        if(!data.length){
            return this.inherited(arguments);
        }
        FC_Comm.when(data,{
            onCmdSuccess: dojo.hitch(this,function(data){
                var store = this.model.store;
                var children = store.getValues(item, 'children');
                dojo.forEach(children, function(child) {
                    // don't delete child if doNotDelete flag is true
                    if(!store.getValue(child, "doNotDelete"))
                        store.deleteItem(child);
                });
                if (data) {
                    var store = this.model.store;
                    if (store) {
                        dojo.forEach(data, function(child) {
                            store.newItem(child, {parent : item, attribute: 'children'});
                        });
                    }
                }
            })
        });
    },

    refresh: function(){

        if(this._storeloaded){
            // Close the store (So that the store will do a new fetch()).
            this.model.store.clearOnClose = true;
            this.model.store.close();

            // Completely delete every node from the dijit.Tree     
            this._itemNodesMap = {};
            this.rootNode.state = "UNCHECKED";
            this.model.root.children = null;

            // Destroy the widget
            this.rootNode.destroyRecursive();

            // Recreate the model, (with the model again)
            this.model.constructor(this.model)

            // Rebuild the tree
            this.postMixInProperties();
            this._load();
            this._storeloaded = false;
        }
    },
    clear: function(){
        this.model.store.load([]);
    }
});

1 个答案:

答案 0 :(得分:1)

您可能会在this fiddle

中找到灵感/答案

recursiveHunt和selectTreeNodeById functions是通过其id找出项目路径的逻辑。它相当过分,你可能会找到一个更好的解决方案(不知道100%你的json是什么数据)..

基本上,使用FilteringSelect并引用此对象中的树。同样对于Tree,引用select。 然后为你的树,钩入加载函数(也称为刷新afaik),然后依次选择,使用onBlur启动选择treenode。

var combo = new dijit.form.FilteringSelect({
    onBlur: function() {
        // called when filter-select is 'left'
        if (this.validate()) {
            // only act if the value holds an actual item reference
            var id = this.get("value");
            var name = this.get("displayedValue");
            this.tree.selectNode(id);
        }
    }
});
var tree = new dijit.Tree( {  ....
    onLoad: function() {
        combostore.setData(this.model.store._arrayOfAllItems);
    },
    onClick: function(item) {
        // uses 'this.combo', must be present
        // also, we must have the same 'base store' for both combo and model
        var _name = this.model.store.getValue(item, this.combo.searchAttr);
        this.combo.set("item", item,  false, _name);
    },
    selectNode: function(lookfor) {
        selectTreeNodeById(this, lookfor);
    },
    combo: combo // <<<<<<
});
combo.tree = tree // <<<<<<

确保模型具有rootId,并且您的select.searchAttr与tree.model.labelAttr匹配。请参阅小提琴上的工作样本