PDA

View Full Version : ExtJs 4.1 : Is calling doLayout() method a must after adding child to a parent?



netemp
27 Jun 2012, 6:55 AM
In our application, we have a tabpanel in which we are adding/removing the panels dynamically.


The panels get added at the click of a menu item by the following code in menu handler:



Ext.getCmp('mainTabPanel').add(getPanel());


Here getPanel() method returns the panel after creating it.

In this context, could someone guide at the following:

a. Is it necesarry to call doLayout() on mainTabPanel after the add method?

b. Will a call to doLayout() not slow the rendering?

c. Will a call to doLayout() take care of all the issues related to rendering, like scrollbars esp.?

d. The method getPanel() should return an already created panel (using Ext.create) or should it return a config object (having xtype:'panel')? Which one should be preferred for better performance keeping time in mind?

Thanks for any help in advance.

scottmartin
27 Jun 2012, 12:51 PM
You will need to call doLayout to ensure your layout is properly calculated.

I would think referencing a panel id (itemId) directly would provide faster access than cycling through xtypes, but I am not sure how your getPanel is setup.

Scott.

netemp
27 Jun 2012, 10:59 PM
Thanks for the reply Scott.

Assuming that the id of main tab panel is 'mainTabId' and that of the child panel is 'panelId', thus, could you please guide at following:

1. .Should I call doLayout() on panel or main tab panel? That is, Ext.getCmp('mainTabId').doLayout() or Ext.getCmp('panelId').doLayout()?

2. Also, in getPanel(), should I create panel using Ext.create and then return it, or its preferable to return a panel object specifying xtype?

Thanks again.

sword-it
27 Jun 2012, 11:16 PM
HI!

You have to call dolayout() method of container in which you are adding elements.
like , if you are adding a textfield in a panel, you have to call dolayout () method of panel, not the textfield.

dolayout() will detect the changes in contents of container and then do lay outing based on the same.

Also, it depends on your choice whether to use
Ext.create or Xtype, Both will work finer, but my opinion is to return an xtype instead of Ext.create.

evant
27 Jun 2012, 11:19 PM
No, you don't need to call doLayout. You can easily verify it:



var p = new Ext.panel.Panel({
renderTo: document.body,
width 200,
height: 200,
layout: 'fit'
});

p.add({
title: 'Foo'
});

netemp
28 Jun 2012, 12:28 AM
Thanks for the posts Sword-It and Evant.

@Sword-Id: You have really made things very clear. Thanks.

@Evant: I was actually under the same impression that we don't need to call doLayout() after adding the child. But when it gets a bit complicated, for example, a panel having a form at north, grid at bottom, and form at south and say it uses ux.center layouts for form and selection model at the grid. If such a panel is added to some tabpanel dynamically then the center layout stops working and forms fall towards left if the call to doLayout() is not made.

We faced such a situation and only after this we realized that its mandatory and safer to call doLayout() of the parent panel after a child has been added to it.

The issue with a call to doLayout() is that it increases the rendering time.

So any thoughts on this that how can this time consumed due to doLayout() be reduced? As in, any other alternative over doLayout()?

Thanks for the time so far.

evant
28 Jun 2012, 12:30 AM
It's not "safer" to call doLayout, instead, you should fix up your code so that you don't need to call it.

netemp
28 Jun 2012, 12:47 AM
Thanks Evant.

Below is a test case (assuming you will include the file for ux.center), in which a panel is getting dynamically added to a tab panel on click of a button.



<html>
<head>
<title>Test Page</title>
<link rel='stylesheet' href='resources/extjs/resources/css/ext-all.css' />
<style type='text/css'>
.ux-layout-center-item {
margin:0 auto !important;
text-align:left;
}
.ux-layout-center .x-panel-body, body.ux-layout-center {
text-align:center;
}
</style>
<script type='text/javascript' src='resources/extjs/ext-all-dev.js'></script>
<script type='text/javascript' src='resources/js/layouts/center.js'></script>
<script type='text/javascript'>
Ext.onReady(function() {
/*Returning the top form below*/
function getForm(){
var formObj = {
xtype:'form',
region:'north',
height:100,
width:150,
layout:'ux.center',
items:[
{
xtype:'container',
width:200,
items:[
{
xtype:'textfield',
width:100,
fieldLabel:'test',
labelWidth:50
}
]
}
]
};
return formObj;
}
/*Returning the grid below*/
function getGrid(){
var sm = Ext.create('Ext.selection.CheckboxModel');
var store = Ext.create('Ext.data.Store',{
fields:[
{name:'test', type:'string'}
],
data:[
{'test':'val1'},
{'test':'val2'},
{'test':'val3'}
]
});
var gridObj = {
xtype:'grid',
region:'center',
store:store,
selModel:sm,
columns:[
{
header:'Test',
dataIndex:'test'
}
]
};

return gridObj;
}

/*Returning the panel below*/
function getPanel(){

var panel = {
xtype:'panel',
title:'testwin',
id:'testPanel',
height:400,
width:600,
layout:'border',
items:[
getForm(),//Callling form function
getGrid()//Calling grid function
]
};

return panel;
}

//Creating the main tab panel
Ext.create('Ext.tab.Panel',{
renderTo:Ext.getBody(),
id:'mainTab'
});

//Creating the button
Ext.create('Ext.Button', {
text: 'Click me',
renderTo: Ext.getBody(),
handler: function() {
Ext.getCmp('mainTab').add(getPanel());
//Ext.getCmp('testPanel').doLayout();//Call to doLayout() commented
}
});
});
</script>
</head>
<body>
</body>
</html>


If the call to doLayout() is not made after the addition then the ux.center at the top does not get applied and form falls towards left.

But if the call is made to doLayout() then the textfield appears in the center properly as per the layout ux.center as shown in the screenshots attached.

Could you please share what is wrong with the code so that the call to doLayout() can be removed, as we too want to avoid that.

Thanks again.

3661736618

evant
28 Jun 2012, 1:00 AM
You can't use a border layout inside an item that is auto-sized.



Ext.onReady(function() {
/*Returning the top form below*/
function getForm() {
var formObj = {
xtype: 'form',
region: 'north',
height: 100,
items: [{
xtype: 'container',
width: 200,
items: [{
xtype: 'textfield',
width: 100,
fieldLabel: 'test',
labelWidth: 50
}]
}]
};
return formObj;
}

/*Returning the grid below*/
function getGrid() {
var sm = Ext.create('Ext.selection.CheckboxModel');
var store = Ext.create('Ext.data.Store', {
fields: [{
name: 'test',
type: 'string'
}],
data: [{
'test': 'val1'
}, {
'test': 'val2'
}, {
'test': 'val3'
}]
});
var gridObj = {
xtype: 'grid',
region: 'center',
store: store,
selModel: sm,
columns: [{
header: 'Test',
dataIndex: 'test'
}]
};

return gridObj;
}

function getPanel() {

var panel = {
xtype: 'panel',
title: 'testwin',
layout: 'border',
items: [getForm(), getGrid()]
};

return panel;
}

//Creating the main tab panel
var main = Ext.create('Ext.tab.Panel', {
renderTo: Ext.getBody(),
width: 400,
height: 400
});

//Creating the button
Ext.create('Ext.Button', {
text: 'Click me',
renderTo: Ext.getBody(),
handler: function() {
Ext.suspendLayouts();
var newItem = main.add(getPanel());
main.setActiveTab(newItem);
Ext.resumeLayouts(true);
}
});
});

netemp
28 Jun 2012, 1:06 AM
Thanks Evant. But with your solution, still the form is falling towards left and ux.center is not having any effect as shown in the attached screenshot.

36619

samsonasu
30 Aug 2012, 12:05 PM
*bump*

I have doLayout calls sprinkled all over my codebase that I hate, but without them the pages simply don't render consistently. I've been spending a lot of time in Sencha Touch 2 lately and now I'm back to ExtJS and I really was hoping this has been fixed across the framework, but it appears that is has not.