我正在向TreePanel添加自定义上下文菜单。 当我为上下文菜单设置单独的函数时,这一切都正常工作,但是如果我点击其中一个选项然后再次查看上下文菜单,我遇到的问题是上下文菜单项最终会加倍/三倍。
我浏览了其他上下文菜单示例,并提出了this one by Aaron Conran我几乎“偷”了批量添加了一些东西,将函数直接添加到Ext.ext.treePanel配置中。这给了我一个关于“oe is undefined”的错误,它似乎在树配置中引用了“contextmenu:this.onContextMenu”。
我认为这可能与我定义所有这些的方式有关,所以我决定将Ext.ext.TreePanel与我的函数一起扩展为一个学习练习。
不幸的是,当页面试图构建TreePanel时,我已经设法解决了扩展TreePanel的问题,现在又回到了“oe is undefined”。我已经浏览了一下,我不确定是什么导致了这个问题,所以任何帮助或建议都会非常感激。
以下是用于定义/构建树面板的代码。我希望它不会太可怕。
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
}
});
总而言之;在我的上下文菜单功能中有更好的方法吗?
if(n.parentNode.id =='treeroot'){ 基本上,如果点击的节点是顶级我只想给用户一个添加子选项,而不是在上面/下面添加。
提前感谢您的帮助
答案 0 :(得分:5)
在您的siteTree类的实例化中,您有:
listeners: {
contextmenu: this.onContextMenu
}
但是,在实例化时,this.onContextMenu并未指向您在siteTree中定义的onContextMenu方法。
修复它的一种方法是从包装函数中调用该方法:
listeners: {
contextmenu: function() {
this.onContextMenu();
}
}
假设你没有覆盖监听器配置中的范围'this'将指向执行监听器时的siteTree实例。
但是,既然您已经在siteTree类中定义了上下文菜单,那么您也可以在那里定义监听器:
constructor: function( config ) {
siteTree.superclass.constructor.call(this, config);
this.on('contextmenu', this.onContextMenu);
}
确保使用树删除上下文菜单也是一个好主意。这使您的siteTree定义:
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;
}
}
});
答案 1 :(得分:1)
昨天我遇到了这个问题。上下文菜单中重复项和重复项的问题是由于extjs向具有相同ID的页面添加多个元素。每次调用this.contextMenu.showAt(xy)时,都会向页面添加ID为“treeContextMenu”的div。大多数浏览器,特别是IE,处理这个问题很糟糕。解决方案是在添加新的上下文菜单之前删除旧的上下文菜单。
以下是我的代码的删节版本:
var old = Ext.get("nodeContextMenu");
if(!Ext.isEmpty(old)) {
old.remove();
}
var menu = new Ext.menu.Menu({
id:'nodeContextMenu',
shadow:'drop',
items: [ ... ]
});
menu.showAt(e.xy);
答案 2 :(得分:1)
我建议永远不要使用硬编码ID。 @aplumb建议清理DOM以重用现有ID。好的,但是当你不再需要DOM中的小部件/元素时,我建议你清理DOM 和你应该永远不会重用ID 。
var someId = Ext.id( null, 'myWidgetId' );
var someElement = new SuperWidget({
id: someId,
...
});
答案 3 :(得分:1)
只是添加到猫头鹰的答案
这一点:
listeners: {
contextmenu: this.onContextMenu
}
在加载javascript文件时执行。该阶段的this
很可能指向窗口对象。
答案 4 :(得分:1)
修复它的一个简单方法是在上下文菜单的hide事件中添加监听器,这样就可以销毁它。
new Ext.menu.Menu(
{
items:[...],
listeners: { hide: function(mn){ mn.destroy(); } }
}
).show(node.ui.getAnchor());
)