PDA

View Full Version : [INFOREQ] [4.0.7] add grid to container at runtime throws error



Reggae
24 Oct 2011, 1:20 AM
When trying to a add a grid to a container at runtime (the container is part of a viewport-container) an error is thrown (in ExtJs 4.0.2a that works fine):

Type error 'undefined is not an object (evaluating child.header.removeCls')



Ext.define('BE.view.StammdatenView', { extend: 'Ext.container.Container',
alias: 'widget.BE-view-StammdatenView',


/**
*Initializer
*/
initComponent: function() {

var north = Ext.create('Ext.panel.Panel', {
region:'north',
itemId:'WeluPdmStammdatenRegionNorth',
margins: '0 0 0 0',
split: true,
collapsible: true,
collapseMode: 'mini',
collapsed: true,
layout: 'accordion',
viewConfig: {
loadMask: false
},
activeItem: 0
});


var west = Ext.create('Ext.panel.Panel', {
region:'west',
title:BE.core.I18n.get('WeluPdm', 'Strukturen'),
itemId:'WeluPdmStammdatenRegionWest',
margins: '0 0 0 0',
width: 300,
split: true,
collapsible: true,
collapsed: true,
padding: '3px',
layout: {
type: 'accordion'
},
viewConfig: {
loadMask: false
},
activeItem: 0
});


var south = Ext.create('Ext.panel.Panel', {
region:'south',
itemId:'WeluPdmStammdatenRegionSouth',
margins: '0 0 0 0',
height: 200,
title: BE.core.I18n.get('WeluPdm', 'StammdatenSouthTitel'),
split: true,
collapsible: true,
collapseMode: 'mini',
collapsed: true,
layout: 'accordion',
viewConfig: {
loadMask: false
},
activeItem: 0
});


var east = Ext.create('Ext.panel.Panel', {
region:'east',
title:BE.core.I18n.get('WeluPdm', 'Erweiterungen'),
itemId:'WeluPdmStammdatenRegionEast',
margins: '0 0 0 0',
padding: '3px',
width: 500,
split: true,
collapsible: true,
collapsed: true,
layout: {
type: 'accordion'
},
viewConfig: {
loadMask: false
},
activeItem: 0
});


var center = Ext.create('Ext.panel.Panel', {
region: 'center',
itemId: 'WeluPdmStammdatenRegionCenter',
layout: {
type: 'card'
},
margins: '0',
padding: '3px'
});


config = {
layout: 'border',
items: [north,
west,
south,
east,
center]
};
Ext.apply(this, config);
this.callParent(arguments);
},

/**
*executes adefined function when a region of the viewport is selected
*
*@param region
*@param PanelObject
*@param objectAction
*/
selectPanel: function(region, PanelObject, objectAction) {
switch (region) {
case'west':
switch (WestPanelObject) {
case'artikelAnonym':
var eW = this.getRegionWest();
eW.remove('WeluPdmStammdatenArtikelMarkenanonymWestDefaultPanel');
var item = {};
Ext.apply(item, {
xtype: 'BE-view-stammdaten-artikelMarkenanonym-KlassifizierungTree',
id: 'WeluPdmStammdatenArtikelMarkenanonymWestKlassifizierungTree',
collapsed: false
});
eW.add(item);
eW.layout.setActiveItem('WeluPdmStammdatenArtikelMarkenanonymWestKlassifizierungTree');
eW.doLayout();
eW.expand();
break;
}
}
},

/**
*populates a given region(center,north,west,south,east)
*of a container with appropriate items
*
*@paramregion
*@paramsubModulePath
*/
setRegion: function(region, subModulePath) {
if (region == 'center') {
this.cleanAllRegions();
this.collapseRegions();
}
var regionObject = this.getRegion(region);
if (regionObject !== undefined) {
if (regionObject.items.items.length > 0) {
Ext.each(regionObject.items.items, function(item) {
if (item.store !== undefined) {
item.loadMask = false;
}
});
}
regionObject.removeAll();
var regionPath = subModulePath + '/' + region;;
var items = this._loadRegionItems(regionPath);
if (items.length > 0) {
var expandRegion = false;
Ext.each(items, function(expItem) {
if (!expItem.collapsed && !expandRegion) {
expandRegion = true;
}
});
regionObject.add(items);
}
regionObject.doLayout();
if (region == 'center') {
expandRegion = true ? regionObject.expand() : regionObject.collapse();
} else {
if (expandRegion) {
regionObject.expand();
}
}
}
},

/**
*@param region
*@returns a region component
*/
getRegion: function(region) {
switch(region) {
case'center':
returnthis.getComponent('WeluPdmStammdatenRegionCenter');
break;
case'north' :
returnthis.getComponent('WeluPdmStammdatenRegionNorth');
break;
case'west' :
returnthis.getComponent('WeluPdmStammdatenRegionWest');
break;
case'south' :
returnthis.getComponent('WeluPdmStammdatenRegionSouth');
break;
case'east' :
returnthis.getComponent('WeluPdmStammdatenRegionEast');
break;
}
},

/**
*expands agiven region of the container
*
*@param region
*/
expandRegion: function(region) {
if (this.items) {
var eRegion = this.getRegion(region);
if (eRegion.items) {
eRegion.expand();
if (region == 'north' || region == 'south') {
if (eRegion.items.items.length > 0) eRegion.items.items[0].expand();
} else {
if (eRegion.items.items.length > 0) {
Ext.each(eRegion.items.items, function(item) {
item.expand();
});
}
}
}
eRegion.doLayout();
}
},

/**
*Collapses a given Region
*
*@paramregion
*/
collapseRegion: function(region) {
var eRegion = this.getRegion(region);
eRegion.collapse();
},

/**
*Collapses all regions
*/
collapseRegions : function() {
this.getComponent('WeluPdmStammdatenRegionSouth').collapse();
this.getComponent('WeluPdmStammdatenRegionNorth').collapse();
this.getComponent('WeluPdmStammdatenRegionWest').collapse();
this.getComponent('WeluPdmStammdatenRegionEast').collapse();
},

/**
*removes all items from all regions.
*/
cleanAllRegions : function() {
var northRegion = this.getRegion('north');
if (northRegion.items.items.length > 0) {
northRegion.removeAll();
}
var westRegion = this.getRegion('west');
if (westRegion.items.items.length > 0) {
westRegion.removeAll();
}
var southRegion = this.getRegion('south');
if (southRegion.items.items.length > 0) {
southRegion.removeAll();
}
var eastRegion = this.getRegion('east');
if (eastRegion.items.items.length > 0) {
eastRegion.removeAll();
}
var centerRegion = this.getRegion('center');
if (centerRegion.items.items.length > 0) {
centerRegion.removeAll();
}
},


/**
*@private
*@return {Array} an array of region items fetched from the registry.
*/
_getRegionItems: function(region) {
var items = [];
var config = BE.core.Registry.get('menu/stammdaten/components/' + region);
Ext.each(config, function(component) {
var item = {};
Ext.apply(item, component, {layout: 'fit'});
items.push(item);
});
return items;
},

/**
*@private
*@return {Array} an array of regionitems fetched from the registry.
*/
_loadRegionItems: function(region) {
var items = [];
var config = BE.core.Registry.get(region);
Ext.each(config, function(component) {
var item = {};
Ext.apply(item, component, {layout: 'fit'});
items.push(item);
});
return items;
}
});

christophe.braud
5 Nov 2011, 8:19 PM
I have a similar issue with a tree. Following a pseudo code of the case:


Ext.define('AppTest.view.TestTreeViewAndGrid',{
extend: 'Ext.container.Viewport',
layout: 'border',
initComponent: function() {
var me = this;

Ext.applyIf(me, {
items: [{
xtype: 'panel',
region:'north'
},
{
xtype: 'treepanel',
region:'west'
},
{
xtype: 'gridpanel',
region:'center'
}]
});

var lTree = me.items.items[1];

// setRootNode acces to store under lTree. store is not defined yet at this step.
lTree.setRootNode({text: 'Root', expanded: true});

me.callParent(arguments);
}
}


It's like when initComponent it's call the new instance is not fully initialized. initComponent can only be used to initialize the configuration of the component not to execute some code at this step.

After Ext.create the new instance is fully initialized and we can execute some code to customize the component. But Ext.create it's call outside the component and I don't find anything to define a function that will be call just before Ext.create return the new instance.
To solve this issue I created an ugly patch to overwrite Ext.create like this:

Ext.ns('AppTest.tools.Overwrite');
Ext.ns('AppTest.tools.Original');

AppTest.tools.Original.create = Ext.create;

AppTest.tools.Overwrite.create = function(){
var lNewObj = AppTest.tools.Original.create.apply(this,arguments);
if (typeof lNewObj.afterCreate === 'function') {
lNewObj.afterCreate.apply(lNewObj);
}
return lNewObj;
}

Ext.create = AppTest.tools.Overwrite.create

Ext.define('AppTest.view.TestTreeViewAndGrid',{
extend: 'Ext.container.Viewport',
layout: 'border',
afterCreate: function(){
var lTree = this.items.items[1];
lTree.setRootNode({text: 'Root', expanded: true});
},
initComponent: function() {
var me = this;

Ext.applyIf(me, {
items: [{
xtype: 'panel',
region:'north'
},
{
xtype: 'treepanel',
region:'west'
},
{
xtype: 'gridpanel',
region:'center'
}]
});

me.callParent(arguments);
}
}

Ext.application({
name: 'AppTest',
launch: function() {
Ext.create('AppTest.view.TestTreeViewAndGrid');
}
});

Now with this patch if a class define 'afterCreate' the code will be executed just before Ext.create return the new instance.

evant
5 Nov 2011, 9:35 PM
@Reggae Not sure what that test case is supposed to be showing

@christophe It's difficult to say from what you've posted, because some of the important details of ordering are ambiguous. For example, in your code:

1) Accessing items.items too early
2) Trying to call a method on the tree when it's still an xtype

Would be useful to see a runnable test case.

Reggae
6 Nov 2011, 9:09 AM
Hi Evant,

basically it's quite simple. The application has a viewport with a vbox-layout. One of the vboxes contains a container with a border layout (thats what you see in the example). The regions of this Container are initially empty. Together with the viewport, the application loads a registry with dynamically created objects. When clicking a button or a tab, one or more items are drawn from the registry and added to the empty container-regions they allowed for.

With ExtJs 4.0.2 gpl that works very good. With ExtJs 4.0.7 the application crashes with the mentioned error if an object is added to one of the outer regions. If only the center region is affected everything works as wanted.