3

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();

                    });
Sandeep Pathak
  • 10,567
  • 8
  • 45
  • 57

1 Answers1

5

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/

phusick
  • 7,342
  • 1
  • 21
  • 26
  • I'm not sure what you mean, so I put together an example, please look at it and let me know what you do not like there: [http://jsfiddle.net/phusick/LcPzv/](http://jsfiddle.net/phusick/LcPzv/). Also note, `Tree` emits `open` event, so you may add listener to it instead: `tree.on("open", function(item, node){})`. – phusick Dec 14 '12 at 13:17
  • Hi , have pasted the code . It says JsonTreeStore is not a constructor . If we remove the two require you suggested , tree comes. Any help ? – Sandeep Pathak Dec 17 '12 at 05:59
  • `JsonRestStore` is not a constructor, because in `JsonRestStore` variable is `dojo/aspect` module. `require([/*Array*/], function() {/*Factory*/})` - items in require _array_ must match parameters in _factory_ function. Also [AMD loader](http://livedocs.dojotoolkit.org/loader/amd) is asynchronous, therefore `require(["dijit/TitlePane"])` is not available inside your factory function. Do not mix legacy `dojo.require()` and AMD `require()/define()`. Choose one and stick to it. – phusick Dec 17 '12 at 11:23
  • Thanks to your last code addition I finally fully understand what you are about to achieve. I edited the code to meet your requirements: http://jsfiddle.net/phusick/LcPzv/. I had to subclass `Tree` class, because of some quirky async funky, but now all you need to observe expand/collapse status change is `tree.watch("state", function(key, oldValue, newValue) { /* your handler here */ });`. Hope, this helps. – phusick Dec 17 '12 at 15:35
  • But it does in the jsFiddle, or not? I tested it in Chrome, Firefox and IE9. Might be due to version of Dojo? Required `dojo/Stateful` was introduced in Dojo 1.5, but maybe it does not process array changes properly in other than jsFiddle's 1.7. Anyway, you can call whatever you want instead of `this,set("state", ...)`. This `dojo/Stateful` is just nice and readable pattern... – phusick Dec 18 '12 at 12:15
  • I am using Dojo 1.7 only . Tree is loading correctly and other event are working fine except the watch event – Sandeep Pathak Dec 18 '12 at 12:19
  • What I want to achieve is simple . There is _onExpandoClick Event hander inside tree.js and _state method. _state method saves my session variable which is consumed by -OnExpandoClick overrtidden method in my html . But my -OnExpandoClick gets called before _state method so the very last path is not getting updated to my html. – Sandeep Pathak Dec 18 '12 at 12:21
  • I tried to assign the `this._openedNodes` object into `state` property and it did not work, so maybe it is the same with array (which works fine with Dojo 1.7.4), so try to make it a string. Do you instantiate `MyTree` and not `Tree`? The main point here is that `_expendNode` calls `this.set("state", ...)` only after the `this._openedNodes` object reflect the state of tree, because opening a node is asynchronous and recursive action. – phusick Dec 18 '12 at 12:26
  • Hi Phusick , thank your very much for your continues support. It is finally working for me . I am accepting the answer . Hope to see in other dojo thread. Thanks again. – Sandeep Pathak Dec 18 '12 at 12:31
  • You too have a beautiful day :) – Sandeep Pathak Dec 18 '12 at 12:38