PDA

View Full Version : [CLOSED][3.1] deferredRender on tabpanel is not working correctly



mprice
17 Dec 2009, 5:57 PM
Ext version tested:

Ext 2.2 through 3.1.0


Adapter used:

ext


css used:

only default ext-all.css


Browser versions tested against:

IE8
FF3
Chrome 2


Operating System:

Windows XP,Vista,7


Steps to reproduce the problem:

Place the code below in a test page with only ext js and css
Browse the page
Using firebug, look at the dom for tab 2
That dom will be empty
Resize the browser
See that the tab 2 contents now get rendered


Test Case:

In the code below, the deferredRender:false is supposed to cause all tabs to be rendered immediately upon load. In all previous versions, this was the case. In 3.1, I am finding that the second tab is not rendering its contents until either the window is resized or the tab is clicked on.



Ext.onReady(function () {
var viewport = new Ext.Viewport({
layout: 'border',
items: [{
region:'north',
title:'north',
height:50,
},{
xtype: 'tabpanel',
region:'center',
activeTab: 0,
deferredRender: false,
items: [{
title: 'tab 1',
layout: 'form',
items: [{xtype: 'textfield', fieldLabel: 'field 2'}]
},{
title: 'tab 2',
layout: 'form',
items: [{xtype: 'textfield', fieldLabel: 'field 2'}]
}]
}]
});
});


So when this code is run in 3.1, I see the following results in firebug. Note that the input tag is rendered in the first tab, but the second tab is empty:

17859

Once the tab is clicked on or the window is resized, then note how the contents are then rendered:

17860

This bug is impacting our application in a serious manner. Is there a workaround that I can employ? I believe that this issue started to occur with the layout changes introduced right before the 3.1 release.

Animal
17 Dec 2009, 11:34 PM
A quick fix (and what I always do), is to configure items in a TabPanel (and any card layout) with hideMode: 'offsets'

Animal
17 Dec 2009, 11:35 PM
But also, this will probably fix it:



Ext.override(Ext.Container, {
canLayout: function() {
var el = this.getLayoutTarget(), s, p, z, result = false;
if (el && (el = el.dom)) {
// Displayed elements which are empty and position:absolute, or are empty and within a <td> will
// report offsetWidth and offsetHeight of zero. So temporarily give it padding to see if it acquires dimensions.
(p = (s = el.style).paddingRight, z = s.zoom, s.zoom = 1, s.paddingRight = '1px');
result = !!(el.offsetWidth || el.offsetHeight);
(s.paddingRight = p, s.zoom = z);
}
return result;
}
});

mprice
18 Dec 2009, 4:55 AM
hideMode:offsets did not fix it. But your override did. I will implement and test. Thanks!

mprice
18 Dec 2009, 5:54 AM
After applying this override, the tabs properly do not defer their render, but resizing operations are now significantly slower. I'm afraid that resize is so much slower that this override is not going to work well.

htoyryla
18 Dec 2009, 7:03 AM
I am also experiencing problems with ExtJS 3.1.0 and items in a card layout not getting rendered. The card that is initially active is rendered correctly, but some of the initially hidden cards fail to render even when made active. This happens with an application that worked correctly on 3.0.2. It seems that the problematic cards all contain are grids.

So far the only trick I found to solve the issue was to call doLayout() on the CardLayout whenever the activeItem is changed. Setting layoutOnCardChange (http://www.extjs.com/forum/../deploy/dev/docs/source/CardLayout.html#cfg-Ext.layout.CardLayout-layoutOnCardChange)to true did not help. Animal's override did not help.

I am disappointed at 3.1.0. We are in a hurry to get things done and it seems we must stick with 3.0.2. Too many things break down.

Condor
18 Dec 2009, 7:23 AM
I am disappointed at 3.1.0. We are in a hurry to get things done and it seems we must stick with 3.0.2. Too many things break down.

Upgrading from Ext 3.0.x to Ext 3.1.x is a minor (=level 2) upgrade, so it's not guaranteed that there are no upgrade issues.

For a production environment I wouldn't upgrade from Ext 3.0.x to Ext 3.1.x without rigorous testing.

I would however recommend upgrading to Ext 3.0.3 or even the current Ext 3.0.x trunk to fix some known bugs.

Animal
18 Dec 2009, 7:33 AM
I am also experiencing problems with ExtJS 3.1.0 and items in a card layout not getting rendered. The card that is initially active is rendered correctly, but some of the initially hidden cards fail to render even when made active. This happens with an application that worked correctly on 3.0.2. It seems that the problematic cards all contain are grids.

So far the only trick I found to solve the issue was to call doLayout() on the CardLayout whenever the activeItem is changed. Setting layoutOnCardChange (http://www.extjs.com/forum/../deploy/dev/docs/source/CardLayout.html#cfg-Ext.layout.CardLayout-layoutOnCardChange)to true did not help. Animal's override did not help.

I am disappointed at 3.1.0. We are in a hurry to get things done and it seems we must stick with 3.0.2. Too many things break down.



It could be that some behaviours in Ext that went off course in the 3.* branch from 2 have now been corrected.

We do not know what your app looks like. There could be mistakes in how you use it which relied upon buggy behaviour. Not saying this is definitely the case, but it could be.

Condor
18 Dec 2009, 7:42 AM
A different workaround is to set forceLayout:true in the hidden tabs.

htoyryla
18 Dec 2009, 7:52 AM
A different workaround is to set forceLayout:true in the hidden tabs.

Yes, I tried that already and it works, except for one grid which still doesn't get rendered even if the rest of that card does. Still could figure out what might be wrong with the grid. I am suspecting that the problem is linked to the use of columnLayout. But I am sorry, not easy to post code as the relevant parts are spread out in different modules.

Animal, I am fully aware that our code may contain bugs that were permitted in 3.0.0 and 3.0.2. I have adopted ExtJS in a hurry, did not always find the documentation too helpful, did not have the time to read through the source code, and ended up in some cases finding out what works by trial and error.

Condor
18 Dec 2009, 8:16 AM
Animals fix isn't wrong, but it only works if you specify hideMode:'offsets'. With the default hideMode:'display' the second tab is still not rendered.

IMHO the correct fix should be:

Ext.override(Ext.layout.CardLayout, {
renderItem: function(c){
if(!this.deferredRender && c && c.doLayout && !c.rendered){
c.forceLayout = true;
}
Ext.layout.CardLayout.superclass.renderItem.apply(this, arguments);
}
});

Or simply uncomment the line in the CardLayout constructor:

constructor: function(config){
Ext.layout.CardLayout.superclass.constructor.call(this, config);
// this.forceLayout = (this.deferredRender === false);
},


@Animal: How is your work on separating rendering and layout coming along? This is one of those cases that can really benefit from that change.

htoyryla
18 Dec 2009, 10:03 AM
It could be that some behaviours in Ext that went off course in the 3.* branch from 2 have now been corrected.


BTW, how am I supposed to find out about such developments. I have no ExtJS 2 background, have learned to use ExtJS 3 directly.

htoyryla
18 Dec 2009, 10:54 AM
We do not know what your app looks like. There could be mistakes in how you use it which relied upon buggy behaviour. Not saying this is definitely the case, but it could be.

OK, I was able to get my app rendering ok with 3.1.0 by removing some nesting. Still, I would like to understand why certain nesting configurations work while others don't. In particular, I would like to use nesting for modularity reasons.

Animal
18 Dec 2009, 11:33 AM
OK, I was able to get my app rendering ok with 3.1.0 by removing some nesting. Still, I would like to understand why certain nesting configurations work while others don't. In particular, I would like to use nesting for modularity reasons.

If, at one level of nesting, you omit a layout specification, then no resizing is cascaded down through that level.

Planning the nesting and layout managers of your app is very important.

@Condor, I have a partial fix working at work, and we plan to release it. It does seem very efficient. deferredRender works well if you don't need the DOM unless you activate a card.

And if you do need the DOM (eg an outer FormPanel and each card contains form Fields which must exist), then it will deep render, but without cascading any sizing instructions into hidden cards until you activate the card.

It needs more work. I'm pulling apart the concepts of a cascaded render, and the term "layout". Layout is when a resize occurs, and the layout manager sizes/positions already rendered items.

A deep render only occurs at the afterRender of an outermost Container, or on activation of a previously inactive card (first activation).

The term "canLayout" is ambiguous, and it should not be tested by doLayout (the misnamed method which does a deep render). Deep rendering is always possible if required.

canLayout should be tested by a size-sensitive layout manager. All it would need to do is test if its Container is hidden, and if so, defer the layout until the next afterShow call.

I've sent my code home (I'm on holiday for two weeks now), and I will continue refactoring.

htoyryla
18 Dec 2009, 11:44 AM
If, at one level of nesting, you omit a layout specification, then no resizing is cascaded down through that level.


That is rather obvious... while it is true, it is rather easy to forget the layout setting at times.
In my particular problem, the outer level was a Container with layout='auto'. The problem was not in resizing, but in rendering. Without this container, rendering works.

sudhirhv
21 Jun 2010, 1:20 AM
Hi, I seem to have the same problem in 3.2.1. I have a formpanel with 2 tabs and have given the property 'deferredRender:false' for the tabpanel, when I submit the form the values in the second tab are not submitted.

I have to use hideMode:offsets as a workaround in each tab for the values to be submitted.

Is this bug still open? Please let me know. I am doing some client side validations for fields that are present in 2 tabs, because the fields are not rendered in the second tab, when I click the submit button the fields are not 'red box' marked. I think that with 'deferredRender:false' the redbox would appear.

Please correct me if I am wrong.

EDIT - Ignore this post. with hideMode: Offsets, the invalid fields are marked in the tabs as well

- Thanks
Sudhir