dojodijit.tree

Search in dijit.Tree


In one of my projects I use a dijit.Tree control. I need to add a search to the tree and show only those nodes/leafs which have the searched term in them. However I can't seem to figure out how that can be achieved. Could anybody please help me?


Solution

  • im not entirely sure that your question entirely but it should give hint whereas to go.

    Lets use reference documentation example as offset, there is 1) a store 2) a model and 3) the tree

        var store = new ItemFileReadStore({
            url: "{{dataUrl}}/dijit/tests/_data/countries.json"
        });
    
        var treeModel = new ForestStoreModel({
            store: store,
            query: {"type": "continent"}, // note, this bit
            rootId: "root",
            rootLabel: "Continents",
            childrenAttrs: ["children"]
        });
    
        new Tree({
            model: treeModel
        }, "treeOne");
    

    Interpret the above as such; You have loaded all known countries and continents but 'user' has selected only to show continents by using query on the model - and the hierachy is then represented in a tree structure.

    You want a textbox with searching capeabilities, so we hook into onChange

        new dijit.form.TextBox({
            onChange: function() {
                  ...
            }
        });
    

    First bit, getting variables

    var searchByName = this.get("value");
    var oQuery = treeModel.query;
    

    Next, set a new query on the model - preserving the old ones with an object mixin

    treeModel.query = dojo.mixin(oQuery, { name: '*'+searchByName+'*' });
    

    Last, notify the model and its tree that changes has occurred - and requery the visible items.

    treeModel._requeryTop();
    

    NB If the top-level item (for ForestModel) is not visible, none of its child elements will show, even if the search-string matches those. (Examplewise, Alabama is not shown if US Continent is not matched by query)

    EDIT

    As OP has the agenda to go by the 'NB', this may not fit needs 100% but its what dojo offers with dijit.Tree.. As it will get rather a lengthy process to recode the model/store queries to include parentbranches up until root i will not do this here - but there are a few tricks still ;)

    var tree = new dijit.Tree( {
       /**
        * Since TreeNode has a getParent() method, this abstraction could be useful
        * It sets the dijit.reqistry id into the item-data, so one l8r can get parent items
        * which otherwise only can be found by iterating everything in store, looking for item in the parent.children
        *
       */
       onLoad : function() {
           this.forAllNodes(function(node) {
                // TreeNode.item <-- > store.items hookup
                node.item._NID = node.domNode.id
           });
       },
       /* recursive iteration over TreeNode's
        * Carefull, not to make (too many) recursive calls in the callback function..
        * fun_ptr : function(TreeNode) { ... }
       */
       forAllNodes : function(parentTreeNode, fun_ptr) {
            parentTreeNode.getChildren().forEach(function(n) {
                 fun_ptr(n);
                 if(n.item.children) {
                     n.tree.forAllNodes(fun_ptr);
                 }
            })
       }
    });
    

    (non-tested, but might just work) Example:

    // var 'tree' is your tree, extended with
    tree.forAllNodes = function(parentTreeNode, fun_ptr) {
            parentTreeNode.getChildren().forEach(function(n) {
                 fun_ptr(n);
                 if(n.item.children) {
                     n.tree.forAllNodes(fun_ptr);
                 }
            })
    };
    // before anything, but the 'match-all' query, run this once
    tree.forAllNodes(tree.rootNode, function(node) {
        // TreeNode.item <-- > store.items hookup
        node.item._NID = node.domNode.id
    });
    
    // hopefully, this in end contains top-level items
    var branchesToShow = [] 
    
    // run fetch every search (TextBox.onChange) with value in query
    tree.model.store.fetch(query:{name:'Abc*'}, onComplete(function(items) {
       var TreeNode = null;
       dojo.forEach(items, function(item) {
           TreeNode = dijit.byId(item._NID+'');
           while(TreeNode.getParent() 
                 && typeof TreeNode.getParent().item._RI == 'undefined') {
              TreeNode = TreeNode.getParent();
           }
           branchesToShow.push(TreeNode.item);
       });
    }});
    
    // Now... If a success, try updating the model via following
    tree.model.onChildrenChange(tree.model.root, branchesToShow);