简体   繁体   中英

dojo how to override dijit class method

I need to override onClick method in the Tree.js. Is there any common way to override dojo/dijit classes methods?

I'm a bit confused, since you were already doing this in the last question you posted .

You've got a few choices, depending on what you want to do.

Clobbering method stubs

In the case of true stubs like onClick , it's potentially as easy as clobbering that method on your widget instance.

Programmatically:

var myWidget = new dijit.Tree({
    ...,
    onClick: function(item, node, evt) {
        /* handler code here */
    }
};

Or declaratively (this is exactly the same as what you were doing in your last question):

<div dojoType="dijit.Tree" ...>
    <script type="dojo/method" event="onClick" args="item,node,evt">
        /* handler code here */
    </script>
</div>

Connecting to method invocations

In other cases, perhaps you need to do something whenever a given method gets called, in which case you could use the widget's connect method (which is a nicer version of dojo.connect that will automatically clear itself when the widget is destroyed). In that case you could do something like this:

Programmatically:

//execute the given function whenever myWidget's onClick method is called
myWidget.connect(myWidget, 'onClick', function(item, node, evt) {
    /* handler code here */
});

Declaratively, this can be done very similarly to the above, except instead of type="dojo/method" , make sure you use type="dojo/connect"

<div dojoType="dijit.Tree" ...>
    <script type="dojo/connect" event="onClick" args="item,node,evt">
        /* handler code here */
    </script>
</div>

Note that when you connect like this, your code will execute after the method whose invocation you are connecting to. If you need to do something before , your best option is probably to dojo.declare your own extension to the widget. If you need to go that far, I'll elaborate, but I think you'll likely be set with one of the above options.

Edit #1: Connecting the dots (no pun intended...oh heck, yes it was)

Since it seems that my comment appended to my answer to the original question was somehow not clear enough, here's a code block modifying the original code in that question based on the simple two steps exactly as I explained in that comment. The only tiny wrinkle is that the arguments passed to _onClick are slightly different.

<div dojoType="dijit.Tree" ...>
    <script type="dojo/connect" event="_onClick" args="node,evt">
        /* handler code here. In this case, item is accessible via node.item */
    </script>
</div>

This solution may feel a bit sub-optimal since it involves connecting to a method that's suggested to be private. However, it's a way that should work regardless of whether openOnClick is true or not. If you are certain you're going to have openOnClick set to true , you could potentially write a single function, then connect it to both onClick and onOpen instead (both get passed the item, then the node).

Edit #2: Common functions, connecting programmatically

To answer your follow-up questions, I'd like to actually address them in reverse order - since if you are interested in connecting programmatically, it will actually make the other question easier to answer.

So first, to answer your connect question: you definitely don't want to be using dojo.byId , as that's not giving you the Tree widget, that's giving you some DOM node (probably the topmost) associated with the widget. As a general rule, dojo methods don't know anything about dijit stuff.

What you do want to be doing, is what I suggested above. Here it is applied as per the code you attempted. Also note that onClick has a capital C - another general rule: widget events use camel case notation, as a way to distinguish them from plain DOM events which don't.

var mytree = dijit.byId("mytree");
mytree.connect(mytree, "onClick", function(item) {
    /* ... */
});

Now, to take that a step further and resolve your other inquiry, if you want to bind some common functionality to onClick and onOpen and onClose , you could define a function first, then connect it to both. This is one of the many things that makes JavaScript awesome - the availability of functions as first-class objects that can be easily passed around.

function handleClick(item) {
    /* do stuff here.
    Inside this function you can assume 'this' is the tree,
    since connect will ensure it runs in-context.
    */
}
var mytree = dijit.byId("mytree");
mytree.connect(mytree, "onClick", handleClick);
mytree.connect(mytree, "onOpen", handleClick);
mytree.connect(mytree, "onClose", handleClick);

Now there's one important remaining question: where should we do this? The best place is likely inside a function passed to dojo.ready (or dojo.addOnLoad , same thing, ready was added as a synonym in 1.4) so that it will run only after:

  • The DOM is parsed by the browser
  • All dojo.require d modules have loaded
  • If you set parseOnLoad: true in djConfig , all widgets defined in the document's HTML will already be instantiated

So, sometime after your dojo.require s, in script, you'd do this:

dojo.ready(function() {
    /* code from previous example goes here */
});

Give it a shot.

Also, if you're interested in a bit of reading, I've actually written about a couple of topics I touched on in this edit:

You could use:

dojo.connect(tree, 'onClick', function(item) {
    /** Your Action **/
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM