Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extended ExtJS Class can't find custom listener function - "oe is undefined"

Tags:

extjs

I'm adding a custom context menu to a TreePanel. This was all working when I had a separate function for the context menu, but I was having problems where the context menu items would end up doubled/tripling up if I clicked on one of the options and then viewed the context menu again.

I had a look around for other contextmenu examples and came up with this one by Aaron Conran I pretty much "stole" it wholesale with a few additions, tacking the function directly into the Ext.ext.treePanel config. This gave me an error about "oe is undefined" which seemed to refer to "contextmenu: this.onContextMenu" in the tree config.

I figured it was probably something to do with the way I was defining all of this, so I decided to look at extending Ext.ext.TreePanel with my function in it as a learning exercise as much as anything.

Unfortunately, having managed to sort out extending TreePanel I'm now back to getting "oe is undefined" when the page tries to build the TreePanel. I've had a look around and I'm not really sure whats causing the problem, so any help or suggestions would be greatly appreciated.

Here is the code that is used to define/build the tree panel. I hope its not too horrible.

siteTree = Ext.extend(Ext.tree.TreePanel,{
        constructor : function(config){
            siteTree.superclass.constructor.call(this, config);
        },
        onContextMenu: function(n,e){
        if (!this.contextMenu){
            console.log('treeContextMenu',n,e);

            if (n.parentNode.id == 'treeroot'){
                var menuitems = [{text:'Add Child',id:'child'}];
            } else {
                var menuitems = 
                        [{text:'Add Child',id:'child'},
                         {text:'Add Above',id:'above'},
                         {text:'Add Below',id:'below'}];
            }

            this.contextMenu = new Ext.menu.Menu({
                id:'treeContextMenu',
                defaults :{
                    handler : treeContextClick,
                    fqResourceURL : n.id
                },
                items : menuitems
            });
        }
        var xy = e.getXY();
        this.contextMenu.showAt(xy);
    }           
});

var treePanel = new siteTree({
    id: 'tree-panel',
    title : 'Site Tree',
    region : 'center',
    height : 300,
    minSize: 150,
    autoScroll: true,

    // tree-specific configs:
    rootVisible: false,
    lines: false,
    singleExpand: true,
    useArrows: true,

    dataUrl:'admin.page.getSiteTreeChildren?'+queryString,
    root: {
        id: 'treeroot',
        nodeType: 'async',
        text: 'nowt here',
        draggable: false
    },
    listeners:{
        contextmenu: this.onContextMenu
    }
});

As a total aside; Is there a better way to do this in my context menu function?

if (n.parentNode.id == 'treeroot') { Basically, if the clicked node is the top level I only want to give the user an add Child option, not add above/below.

Thanks in advance for your help

like image 684
Stephen Moretti Avatar asked Dec 17 '25 22:12

Stephen Moretti


1 Answers

In your instantiation of your siteTree class you have:

listeners: {
    contextmenu: this.onContextMenu
}

However, at the time of the instantiation this.onContextMenu is not pointing to the onContextMenu method you defined in siteTree.

One way of fixing it is to call the method from within a wrapper function:

listeners: {
    contextmenu: function() {
        this.onContextMenu();
    }
}

Assuming you don't override the scope in the listeners config 'this' will be pointing to the siteTree instance at the time the listener is executed.

However, since you are already defining the context menu in the siteTree class, you may as well define the listener there:

constructor: function( config ) {
    siteTree.superclass.constructor.call(this, config);
    this.on('contextmenu', this.onContextMenu);
}

Ensuring the context menu is removed with the tree is also a good idea. This makes your siteTree definition:

var siteTree = Ext.extend(Ext.tree.TreePanel, {
    constructor: function( config ) {
        siteTree.superclass.constructor.call(this, config);
        this.on('contextmenu', this.onContextMenu);
        this.on('beforedestroy', this.onBeforeDestroy);
    },
    onContextMenu: function( node, event ) {
        /* create and show this.contextMenu as needed */
    },
    onBeforeDestroy: function() {
        if ( this.contextMenu ) {
            this.contextMenu.destroy();
            delete this.contextMenu;
        }
    }
});
like image 127
owlness Avatar answered Dec 20 '25 14:12

owlness



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!