PDA

View Full Version : Problem Dynamically Adding Submenus to Menu Items



ventryj
15 Jul 2013, 1:54 PM
I am attempting to recursively call a buildMenu function in one of my controllers in order to dynamically create a menu hierarchy.


buildMenu: function(parentCmp, menuItems) {
var menu = Ext.create("Ext.menu.Menu", {floating: false});
if(parentCmp.getXType() == "menuitem") parentCmp.setMenu(menu);
else parentCmp.add(menu);
for(var i = 0; i < menuItems.length; i++) {
var menuItem = Ext.create("Ext.menu.Item", {text: menuItems[i].name});
menu.add(menuItem);
if(menuItems[i].sub.length > 0) this.buildMenu(menuItem,menuItems[i].sub);
}
}

My menus are populating correctly, but when I attempt to view one of my submenus by mousing over the auto-generated arrow in the browser, the following error is thrown:


Uncaught TypeError: Cannot call method 'getY' of undefined

I am using the setMenu() method of Ext.menu.Item because there is no add() method associated with the class to add a child component (menu in this case). The top level of menus are panels nested in an accordion layout and are displaying correctly; it's just the lower level menus inside of menu items that are not displaying. When I print my submenu components in my browser console, I can see my submenus have been created with the correct values. However, they are not being shown. Any suggestions as to what may be going on here? Please let me know if more clarification is necessary. Thanks.

EDIT: After some more research, I tried building the submenus first and adding them as a 'menu' configs at menu item creation time, as shown in other examples. However, I am still getting the same error in the browser console when mousing over the menu items to expand their submenus. Again, the right arrow is generated on the menu items, signifying a submenu, but the submenu is not displayed and the error is thrown instead.


var menu = Ext.create("Ext.menu.Menu", {floating: false});parentCmp.add(menu);
for(var i =0; i < menuItems.length; i++) {
if(menuItems[i].sub.length > 0) {
var subMenu = Ext.create("Ext.menu.Menu", {floating: false});
for(var j = 0; j < menuItems[i].sub.length; j++) {
var subMenuItem = Ext.create("Ext.menu.Item", {text: menuItems[i].sub[j]});
subMenu.add(subMenuItem);
}
var menuItem = Ext.create("Ext.menu.Item", {text: menuItems[i].name, menu: subMenu});
menu.add(menuItem);
}
else {
var menuItem = Ext.create("Ext.menu.Item", {text: menuItems[i].name});
menu.add(menuItem);
}
}

ventryj
16 Jul 2013, 7:54 AM
I've recreated the issue in a simple test case below.

app.js:


//@require @packageOverridesExt.Loader.setConfig({
enabled: true
});


Ext.application({
views: [
'MyPanel'
],
autoCreateViewport: true,
controllers: [
'MyController'
],
name: 'MyApp'
});

MyPanel:


Ext.define('MyApp.view.MyPanel', { extend: 'Ext.panel.Panel',


height: 250,
width: 400,
layout: {
type: 'border'
},
title: 'My Panel',


initComponent: function() {
var me = this;


Ext.applyIf(me, {
items: [
{
xtype: 'panel',
region: 'west',
itemId: 'navPanel',
width: 150,
layout: {
type: 'accordion'
},
title: 'My Panel'
},
{
xtype: 'panel',
region: 'center',
title: 'My Panel'
}
]
});


me.callParent(arguments);
}


});

MyController:


Ext.define('MyApp.controller.MyController', { extend: 'Ext.app.Controller',


init: function(application) {
this.control({
'#navPanel': {
beforerender: this.build
}


});
},


build: function(navPanel, eOpts) {
var me = this;
var accordPanel,menu,menuItem,subMenu,subMenuItem,i,j,k;
for(i = 0; i < 3; i++) {
accordPanel = Ext.create("Ext.panel.Panel", {title: i+1, layout: {type: 'fit'}});
navPanel.add(accordPanel);
menu = Ext.create("Ext.menu.Menu", {floating: false});
accordPanel.add(menu);
for(j = 0; j < 3; j++) {
menuItem = Ext.create("Ext.menu.Item", {text: j+1});
menu.add(menuItem);
subMenu = Ext.create("Ext.menu.Menu", {floating: false});
menuItem.setMenu(subMenu);
for(k = 0; k < 3; k++){
subMenuItem = Ext.create("Ext.menu.Item", {text: k+1});
subMenu.add(subMenuItem);
}
}
}
}


});


EDIT: After running the app in Firefox (previously using the Chrome), the error message is:


TypeError: this.el is undefined

slemmon
17 Jul 2013, 10:28 AM
Try setting floating to true for the floating menus:



Ext.define('MyApp.view.MyPanel', {
extend: 'Ext.panel.Panel',


height: 250,
width: 400,
layout: {
type: 'border'
},
title: 'My Panel',


initComponent: function () {
var me = this;


Ext.applyIf(me, {
items: [{
xtype: 'panel',
region: 'west',
itemId: 'navPanel',
width: 150,
layout: {
type: 'accordion'
},
title: 'My Panel'
}, {
xtype: 'panel',
region: 'center',
title: 'My Panel'
}]
});


me.callParent(arguments);
}


});




Ext.define('MyApp.controller.MyController', {
extend: 'Ext.app.Controller',


init: function (application) {
this.control({
'#navPanel': {
beforerender: this.build
}




});
},


build: function (navPanel, eOpts) {
var me = this;
var accordPanel, menu, menuItem, subMenu, subMenuItem, i, j, k;
for (i = 0; i < 3; i++) {
accordPanel = Ext.create("Ext.panel.Panel", {
title: i + 1,
layout: {
type: 'fit'
}
});
navPanel.add(accordPanel);
menu = Ext.create("Ext.menu.Menu", {
floating: false
});
accordPanel.add(menu);
for (j = 0; j < 3; j++) {
menuItem = Ext.create("Ext.menu.Item", {
text: j + 1
});
menu.add(menuItem);
subMenu = Ext.create("Ext.menu.Menu", {
floating: true
});
menuItem.setMenu(subMenu);
for (k = 0; k < 3; k++) {
subMenuItem = Ext.create("Ext.menu.Item", {
text: k + 1
});
subMenu.add(subMenuItem);
}
}
}
}


});




Ext.application({
name: 'MyApp',


controllers: [
'MyController'
],


launch: function () {


Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));


Ext.widget('viewport', {
layout: 'fit',
items: [Ext.create('MyApp.view.MyPanel')]
});


}
});

ventryj
17 Jul 2013, 10:39 AM
That fixed it! Figures that three days of headaches was fixed by something so simple! Much obliged. :)