javascriptdojodijit.tree

Dijit Checkbox tree event delegation


I am trying to implement a dijit checkbox tree similar to http://thejekels.com/dojo/cbtree_AMD.html

And overriding a method like this :

      connect.connect( tree, "_onExpandoClick", model, this,function(/*data.item*/ item) {
       console.log("My onExpandoClick");
 });

Dijit Tree javascript file already contains the handler method for this event. My problem is that

I want the above overridden method to be called after tree js method handler have been executed.As per now its always called first.Any idea.(dijit 1.7)

In my setup the below code isn't working :

    require(["dijit/TitlePane"]);

    require([
        "dojo/_base/lang",
        "dojo/dom",
        "dojo/aspect",
        "dijit/CheckboxTree", 
        "dojox/data/JsonRestStore",
        "my_ext/CheckboxForestStoreModel", 
        "dojo/domReady!"
        ], function(dom, Tree, JsonRestStore, CheckboxForestStoreModel) {
            var treeStore = new JsonRestStore({ target: "ObjectTreeServlet/",labelAttribute:"name",allowNoTrailingSlash:true});
            var treeModel = new CheckboxForestStoreModel({
                    store: treeStore,
                    deferItemLoadingUntilExpand: true,
                    rootId: "ROOT",
                    rootLabel: "NETWORK",
                    childrenAttrs: ["children"],
                    query:"?id=0"         

                });

            var treeStateSession= '<%=session.getAttribute("treeState")%>';
            //alert(treeStateSession);
            var tree = new Tree({
                    id : "tree",
                    model : treeModel,
                    showRoot : false,
                    persist: true,
                    setCheckboxOnClick : false,

                    _sessionVal:treeStateSession
                    },
                'treeDiv');

            function getParameterByName(url,name) {
                var match = RegExp('[?&]' + name + '=([^&]*)')
                                .exec(url);
                return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
            }
            dojo.require("dojo.aspect");
            /*
            aspect.after(tree, "_onExpandoClick",  function(item) {
                console.log(tree.getSessionValue());
                document.getElementById("treeState").value=tree.getSessionValue();
                console.log(document.getElementById("treeState").value.length);

            }); */
aspect.after(tree, "_onExpandoClick", function() {
console.log("My onExpandoClick");        

});

Code Inside CheckBoxTree.js :

_state: function(node, expanded){
        // summary:
        //      Query or set expanded state for an node
        if(!this.persist){
            return false;
        }
        var path = array.map(node.getTreePath(), function(item){
                return this.model.getIdentity(item);
            }, this).join("/");
        if(arguments.length === 1){
            return this._openedNodes[path];
        }else{
            if(expanded){
                this._openedNodes[path] = true;
            }else{
                delete this._openedNodes[path];
            }
            var ary = [];
            for(var id in this._openedNodes){
                ary.push(id);
            }
            //console.log(ary.length);
            //cookie(this.cookieName, ary.join(","), {expires:365});
            var sessionVal=ary.join(",");
            console.log("TreeSTATE CheckBOX");

     **//FROM HERE SEND sessionVal TO MAIN HTML PAGE WHERE TREE IS CREATED?**

            //this.getSessionValue(ary.join(","));
        }
    },

What I tried ,which is not giving desired results.:

aspect.after(tree, "_state", function() {
                    console.log("TreeSTATE  "  + tree.getSessionValue());
                    document.getElementById("treeState").value=tree.getSessionValue();

                    });

Solution

  • Use dojo/aspect instead:

    // var aspect = require("dojo/aspect");
    // var lang   = require("dojo/_base/lang");
    
    aspect.after(tree, "_onExpandoClick", lang.hitch(this, function(item) {
        console.log("My onExpandoClick");
    }))
    

    Edit: Also please note, dijit/Tree as well as cbtree/Tree emit onOpen and onClose events, so you can register event listeners for expanding and collapsing node actions:

    tree.on("open", function(item, node) {
        console.log("onOpen:", item, node);        
    });
    
    tree.on("close", function(item, node) {
        console.log("onClose:", item, node);        
    });
    

    Edit #2: According to the discussion below I changed my approach from using dojo/aspect to subclassing Tree (because of some quirky async funky there). So first subclass Tree:

    // var declare  = require("dojo/_base/declare"); 
    // var lang     = require("dojo/_base/lang");
    // var Deferred = require("dojo/_base/Deferred");
    
    var MyTree = declare([Tree], {
    
        persist: true,
    
        _expandNode: function(node, recursive) {
            var dfd = this.inherited(arguments);
            Deferred.when(dfd, lang.hitch(this, function() {
                if (recursive === undefined) {
                    this.set("state", this._objectToArray(this._openedNodes));
                }
            }));
            return dfd;
        },
    
        _collapseNode: function(node) {
            this.inherited(arguments);
            this.set("state", this._objectToArray(this._openedNodes));
        },
    
        _objectToArray: function(object) {
            var arr = [];
            for (var each in object) {
                if (object.hasOwnProperty(each)) {    
                    arr.push(each);
                }
            }
            return arr;
        }
    });
    

    Then you can you can observe expand/collapse state change on MyTree instance:

    tree.watch("state", function(/*String*/key, /*Array*/oldValue, /*Array*/newValue) {
        console.log(newValue);        
    });
    

    See it in action: http://jsfiddle.net/phusick/LcPzv/