PDA

View Full Version : When to set field values?



fermo111
22 Dec 2009, 3:58 PM
Say I have a container, with few components in it. It may be visible or hidden. I create the container, and then I want to interact with the HTML of its descendant components. Is there a point, an event, an override, where I can be sure that all the HTML is in place?

I was under the impression that that might be the 'afterlayout' event. Am I correct or there is some optimization in the rendering process that makes it false?

Thanks

Mike Robinson
23 Dec 2009, 2:30 PM
I've found in several cases in afterrender that everything is not yet rendered.

But what seems to work well ... okay, it is a bit of a "hack" ... is to use defer(500). "Half a second from now it will be ready, and the user really won't know."

Also... I really don't monkey-around with the DOM. For whatever reason, I always let ExtJS do that. I stick to the ExtJS object-structures.

fermo111
23 Dec 2009, 4:06 PM
Also... I really don't monkey-around with the DOM. For whatever reason, I always let ExtJS do that. I stick to the ExtJS object-structures.

That's something I am starting to learn. When I have code with something like el.dom.property sooner or later it is going to fail. But sometime it is so simple to access the dom that does not seem worthwhile to go throughout the trouble of defining a new component just to do the simple thing.

I create a form, ask ext to display it, but I am never really sure when all the HTML has been created. Not after the 'afterrender' that's for sure. At every new extjs release I had to move the code that access the dom, later and later. With ext 3.0.3 I settled with this

this.on('afterlayout', function() {
// do dom handling stuff
}, this, {
single: true
});

but after having read somewhere that v. 3.1 has modified the rendering logic to improve performance, I am wondering if this is sufficient any more. What about components that are initialized as not visible totally or in parts? When will the HTML be available? The answer would be on the 'afterrender' of the single component. Does that mean I have to scatter the handling logic around, in several event handlers?

So my question is: if I wish to create a container, no matter how complex, and, from a single place, an event handler, whatever, know to have all the HTML ready, what this such place would be?

Mike Robinson
24 Dec 2009, 7:22 AM
I've found in several cases in afterrender that everything is not yet rendered.

But what seems to work well ... okay, it is a bit of a "hack" ... is to use defer(500). "Half a second from now it will be ready, and the user really won't know."

Edit: On second glance, I notice that the "Ext.util.Observable.addHandler()" (a.k.a. ".on()") function includes a "delay:" property, which would of course have the same net effect as my use of "defer()." The very existence of this designed-in capability basically says to me that my approach to solving the problem wasn't so "out of line" after all. ~o)

It's reasonable to assume that one of the most frequent ways that "all browsers are not created equal" is in the matter of timing. I see these "very slight delays" used in a lot of code by some of the best writers out there, such as Saki.

fermo111
28 Dec 2009, 12:44 AM
And there is a 'deferredRender' property that by default is true that must be taken care of. It is defined only for TabPanels and CardLayout, but I wonder if there are also other containers that render child components after the user clicks something. Would FieldSet be one of these?

Condor
28 Dec 2009, 12:58 AM
The component itself will be rendered in the afterrender event, but any child components won't be.

You'll have to use the afterlayout event if you want to make sure that all child components are rendered (use single:true to avoid it also being called after a resize).

Example:

listeners: {
afterlayout: {
fn: function(c){
...
},
single: true
}
}

fermo111
28 Dec 2009, 2:36 AM
@Condor: in the following code, the 'afterlayout' fires before the 'afterrender', and very little HTML has been layed out. A call to a 'doLayout' at the end might help, but only if the afterlayout event would be defined without the 'single: true'

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Forms</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css"/>
<script type="text/javascript" src="../../adapter/ext/ext-base.js">
</script>
<script type="text/javascript" src="../../ext-all.js">
</script>
<script type="text/javascript">
Ext.onReady(function(){

var collapsed = true;
var panel = new Ext.Panel({
width: 400,
height: 300,
items: {
xtype: 'form',
title: 'Form1',
labelWidth: 75,
autoHeight: true,
items: [{
id: 'fs1',
xtype: 'fieldset',
checkboxToggle: true,
title: 'User Information',
autoHeight: true,
defaultType: 'textfield',
collapsed: collapsed,
items: [{
id: 'dt1',
xtype: 'datefield',
fieldLabel: 'Date',
width: 100,
name: 'date'
}, {
xtype: 'fieldset',
id: 'fs2',
checkboxToggle: true,
title: 'Other User Information',
autoHeight: true,
defaultType: 'textfield',
collapsed: collapsed,
items: [{
id: 'tm1',
xtype: 'timefield',
fieldLabel: 'Time',
width: 100,
name: 'time'
}]
}]
}]
},

listeners: {
afterlayout: {
fn: function(c){
console.debug('afterlayout'); // logged first. Little HTML
console.debug(panel.el.dom.innerHTML);
},
single: true // without this, the last doLayout would be catched
},

afterrender: function(){
console.debug('afterrender'); // logged second
console.debug(panel.el.dom.innerHTML);
}
}
});

panel.render(document.body);
panel.doLayout(false, true);
});
</script>
</head>
<body>
</body>
</html>

Condor
28 Dec 2009, 2:42 AM
In Ext 3.1 you need to configure collapsed panels with forceLayout:true if they contain fields that you want to access before the panel is expanded.

ps. You shouldn't need to call doLayout after render!

fermo111
28 Dec 2009, 3:35 AM
Hi Condor,


In Ext 3.1 you need to configure collapsed panels with forceLayout:true if they contain fields that you want to access before the panel is expanded.


I tried again the previous example, setting the panel and the fieldsets with forceLayout:true, but the result is still the same, the 'afterlayout' is fired before the 'afterrender' and the HTML is not there. Same thing setting collapsed = false.