extjs contextmenu 单击错误 - 找不到方法......但在错误的控制器中查找

extjs contextmenu click error - method not found... but looking in wrong controller

如何单击此菜单项以启动控制器中的方法。 项目点击成功,但错误消息指出 ExtApplication4.view.main.MainController 上没有名为 "onDownloadTopdayRecapContextButton" 的方法。就是这个问题,你可以看到视图的控制器是 portalRealtime-portalRealtime.

所以它以某种方式指向了错误的控制器。有人可以告诉我我做错了什么吗?

菜单代码

var contextMenuTopday = Ext.create('Ext.menu.Menu', {
items: [{
    text: 'Download Topday Recap',
    iconCls: 'downloadIcon',
    listeners: {
        click: 'onDownloadTopdayRecapContextButton'
    }

网格菜单保存在

Ext.define('ExtApplication4.view.portalRealtime.PortalRealtime', {
extend: 'Ext.panel.Panel',

xtype: 'app-portalRealtime',

itemId: 'portalRealtimeItemID',

requires: [
    'ExtApplication4.view.portalRealtime.PortalRealtimeController',
    'Ext.form.action.StandardSubmit'
],

controller: 'portalRealtime-portalRealtime',

title: 'Main Portal',

layout: {
    type: 'vbox'
},

items: [
//i deleted some grid code here
            collapsible: true,
            collapseDirection: 'left',
            listeners: {

                itemcontextmenu: function (view, rec, node, index, e) {
                    e.stopEvent();                    
                    contextMenuTopday.showAt(e.getXY());
                    return false;
                }
{

您正在视图之外创建上下文菜单,因此它不会继承您的控制器。

在使用下面的代码之前,请滚动到答案的底部以获得更好的解决方案,但这有望说明问题的原因。

如果这不能解决您的问题,请发表评论并提供更完整的代码示例,我会更新我的答案

在这些情况下,您可以手动传递一个控制器,但您需要作为父控制器传递,因为如果您在多个组件上重复使用相同的控制器(例如,当您销毁一个控制器时,它破坏了控制器,而另一个没有)

所以您可以像这样在您的视图中创建:

Ext.define('ExtApplication4.view.portalRealtime.PortalRealtime', {
    initComponent:function(){
        this.callParent(arguments);
        this.contextMenuTopday = Ext.create('Ext.menu.Menu', {
            controller:{
                parent: this.getController()
            },
            items: [{
                text: 'Download Topday Recap',
                iconCls: 'downloadIcon',
                listeners: {
                    click: 'onDownloadTopdayRecapContextButton'
                }
            }]
        });
    }

然后,您可以访问 contextMenuTopday 属性,而不是使用变量来访问上下文菜单,因为您在子项目中,您可能需要遍历到您的实际视图,这是执行此操作的最简单方法通过组件上可用的 up 方法,您需要确保包含一个 xtype 来执行此操作:

Ext.define('ExtApplication4.view.portalRealtime.PortalRealtime', {
    xtype:'portalrealtime'

然后您可以在上下文菜单中执行以下操作:

itemcontextmenu: function (view, rec, node, index, e) {
    this.up('portalrealtime').contextMenuTopday.showAt(e.getXY());
}


更好的方法

最好看这个fiddle:https://fiddle.sencha.com/#view/editor&fiddle/1qpn

将您的菜单定义为自己的菜单class:

Ext.define('Example.ContextMenu', {
    xtype:'testmenu',
    extend:'Ext.menu.Menu',
    items: [{
            text: 'Download Topday Recap',
            iconCls: 'downloadIcon',
            listeners: {
                click: 'onDownloadTopdayRecapContextButton'
            }
        }]
    });

在您的控制器上为 itemcontextmenu 事件使用一个方法(无论如何这都很好,因为它提供了更好的关注点分离): 项目上下文菜单:'showContextMenu'

然后向您的 portalRealtime-portalRealtime 控制器添加一些新方法:

getContextMenu:function(){
    if(!this.contextMenu){
        this.contextMenu = this.getView().add({xtype:'testmenu'});
    }
    return this.contextMenu;
},
showContextMenu:function (view, rec, node, index, e) {
    // we can't use showAt now we have added this to our view, as it would be positioned relatively.
    this.getContextMenu().show().setPagePosition(e.getXY());

}

我们在这里做的是将上下文菜单添加到视图,因此它继承了控制器(如果提供的话,还有一个视图模型)。

在控制器上为 listeners/button 处理程序等调用方法的最佳方法是仅将方法名称指定为字符串,即:

listeners:{
    itemcontextmenu: 'showContextMenu'
}

这将自动查找负责的控制器并使用正确的方法。

如果您需要从组件内部调用,您会发现 this.getController() 失败,除非您调用控制器附加到的实际组件 - 即您是从子组件调用。在这些情况下,您可以使用 this.lookupController() 找到 inherited/responsible 控制器,然后从此处调用任何方法,例如this.lookupController().myMethod()