0

I want to write a ComboBox which lets the user type in a query and at the same time lets him select a value from a tree. I have tried writing a tree-select but if I change the code to inherit from dijit.form.ComboBox instead of a dijit.form.Select, the code breaks.

Here is what I had tree for tree 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);
            }
        });
    }
});

I had tried replacing the code for combobox like this:

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

Please help me rectify it. Thanks in advance!

Adding the code for 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([]);
    }
});
4

1 回答 1

1

Possibly you will find inspiration / answer in this fiddle

The recursiveHunt and selectTreeNodeById functions are logic to seek out the path of an item by its id. Its quite excessive and you may find a better solution (dont know 100% what data your json is like)..

Basically, use FilteringSelect and reference the tree in this object. Also for Tree, reference the select. Then for your tree, hook into load function (also called on refresh afaik) and in turn for the select, use onBlur to initate selecting 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 // <<<<<<

Make sure that the model has a rootId, and also that your select.searchAttr matches tree.model.labelAttr. See working sample on the fiddle

于 2012-06-12T14:04:53.133 回答