Search code examples
model-view-controllerextjscontrollernavigateurl

newCard.fireEvent is not a function for ExtJS 5.1.1


I have a Viewport and it has two content: Menu and Main Content. During click event for Menu items, I get this error: Uncaught TypeError: newCard.fireEvent is not a function

What am I missing for navigate function? Here are View and Controller;

MainView:

Ext.define('CalTable.view.MainView', {
    extend: 'Ext.container.Viewport',
    alias: 'widget.mainview',

    requires: [
        'Ext.menu.Menu',
        'Ext.menu.Item',
        'Ext.form.Label'
    ],

    itemId: 'mainView',
    layout: 'border',
    defaultListenerScope: true,

    items: [
        {
            xtype: 'panel',
            region: 'west',
            split: true,
            itemId: 'menuPanel',
            width: 150,
            title: 'Menu',
            items: [
                {
                    xtype: 'menu',
                    floating: false,
                    itemId: 'menu',
                    items: [
                        {
                            xtype: 'menuitem',
                            itemId: 'home',
                            text: 'Home',
                            focusable: true
                        }, {
                            xtype: 'menuitem',
                            itemId: 'folioList',
                            text: 'Folio List',
                            focusable: true
                        }, {
                            xtype: 'menuitem',
                            itemId: 'calendar',
                            text: 'Calendar',
                            focusable: true
                        }
                    ],
                    listeners: {click: 'onMenuClick'}
                }
            ]
        }, {
            xtype: 'panel',
            region: 'center',
            itemId: 'contentPanel',
            layout: 'card',
            scope: this,
            items: [
                {
                    xtype: 'panel',
                    itemId: 'homePanel',
                    title: 'Home',
                    layout: {
                        type: 'vbox',
                        align: 'center',
                        pack: 'center'
                    },
                    items: [
                        {
                            xtype: 'label',
                            text: 'Home View'
                        }
                    ]
                }, {
                    xtype: 'panel',
                    itemId: 'folioPanel',
                    title: 'Folio List',
                    layout: {
                        type: 'vbox',
                        align: 'center',
                        pack: 'center'
                    },
                    items: [
                        {
                            xtype: 'label',
                            text: 'Folio List View'
                        }
                    ]
                }, {
                    xtype: 'panel',
                    itemID: 'calendarPanel',
                    title: 'Calendar',
                    layout: {
                        type: 'vbox',
                        align: 'center',
                        pack: 'center'
                    }, 
                    items: [
                        {
                            xtype: 'label',
                            text: 'Calendar View'
                        }
                    ]
                }
            ]
        }
    ],

    onMenuClick: function(menu, item, e, eOpts) {
        location.hash = item.itemId;
    }
});

and of course Controller:

Ext.define('CalTable.controller.TheController', {
    extend: 'Ext.app.Controller',
    requires: ['Ext.util.History'],

    refs: {
        contentPanel: '#contentPanel',
        menu: '#menu',
        menuPanel: '#menuPanel'
    },

    onLaunch: function () {
        Ext.History.init();
        Ext.History.on('change', this.navigate, this);
        this.navigate(window.location.hash);
    },

    navigate: function (id) {
        if (id) {
            if (id[0] == '#') id = id.slice(1);
            this.getContentPanel().layout.setActiveItem(id + 'Panel');
            this.getMenu().items.each(function (item) {
                if (item.href == '#' + id) {
                    item.disable();
                    window.document.title = item.text;
                }
                else {
                    item.enable();
                }
            });
        }
    }
});

Solution

  • The error is caused in this line:

    this.getContentPanel().layout.setActiveItem(id + 'Panel');
    

    because the underlying issue is that the ids of the menu items and the cards have to match.

    You have the menu items

    home
    folioList
    calendar
    

    but the ids you have in your card layout are

    homePanel
    folioPanel
    calendarPanel
    

    So when the menu item with id folioList is clicked and subsequently setActiveItem("folioListPanel") is executed, but no item with id folioListPanel exists, that obscure error is thrown in ExtJS.

    While changing the id should fix the problem at hand, what you definitely also want to do is to amend the controller to check whether the item really exists before navigating, because navigation can also be executed through a user-changed anchor, and you don't want your user to break your app that way.