tags:

views:

186

answers:

3

I've created a panel bundled with an Ext.Template. This panel is contained in another panel that starts its life collapsed.

id:             'myPanel',
title:          'My Title',
layout:         'border',
collapsible:    true,
collapsed:      true,
hideCollapseTool:true,
bodyBorder:     false,
height:         300,
bodyStyle:      'background:#F9F9F9;',
items: [{
    id:         'myDisplayPanel',
    bodyStyle:  'background:transparent;',
    width:      300,
    border:     false,
    margins:    '5 5 5 5',
    region:     'west',
    tpl:        new Ext.Template([
                    'some template'
                ])
},
{
    id:         'myForm',
    xtype:      'form',
    bodyStyle:  'background:transparent;',
    border:     false,
    margins:    '5 5 5 5',
    region:     'center',
[...]

This template-panel is supposed to be updated as the result of a row select in a neighbouring grid. But I get an error the first time I call .update(data); on the myDisplayPanel, as it contains no body element.

myGridSelectionModel: new Ext.grid.RowSelectionModel({
    singleselect: true,
    listeners: {
        rowselect: function(sm,rowIdx,r) {
            Ext.getCmp('myDisplayPanel').update(r.data);
            Ext.getCmp('myPanel').expand(true);
        }
    }
}),

The call to myDisplayPanel.update() causes an error when Ext tries to call the template.overwrite function with myDisplayPanel.body as the first param.

function(b,a,c){b=Ext.getDom(b);b.innerHTML=this.applyTemplate(a);

Is it possible somehow to force Ext to generate a body element for this hidden panel before it is beeing shown? I've tried to expand the element prior to updating it, but this has now effect...

A: 

You might try Panel's elements config, which from the docs is "A comma-delimited list of panel elements to initialize when the panel is rendered." So e.g.,

elements: ['header','body']

However it already defaults to 'body' only, so it may just be that the panel is truly not rendered yet when you are updating it. Try reversing the order of your calls so that the container is expanded first (should force the child panel to render) then update it.

bmoeskau
I'm sorry for the late answer, but my youngest son was born last sunday keeping me kinda busy. Your proposed fix does not seem to work. I've also tried to change the order of my calls, but to no avail. For now my only solution (workaround) is to drop the collapsed parameter altogether.
Ivar Bonsaksen
The reason that reversing the order of the calls did not work is that when the myPanel container is expanded with an animation it became an asynchronous call. Layouts by default are not performed on collapsed/hidden containers, so the initial layout of myPanel's children had not yet been rendered when update was called on myDisplayPanel immediately after.
Kevin
A: 

Collapsed panels (and hidden containers in general) by default do not layout their children until they first become visible. You can override this behavior by setting forceLayout: true on the collapsed container. As the name suggests, this will force the container to perform its layout whether it is visible or not. Note that in your case this would be myPanel that would need this configuration, not myDisplayPanel.

Kevin
Yes, I've noticed this setting, but unfortunately it didn't work for me for some still unknown reason. I've abandoned the collapsed approach for this panel altogether, but I'm going to accept your answer as it in theory should solve this kind of problem.
Ivar Bonsaksen
Sorry this didn't work out for you. If you want to dig in further, I usually debug this sort of thing by setting a breakpoint on the update line in firebug, then use the console/watch to browse Ext.getCmp('myDisplayPanel'), checking the rendered and el properties for it and its ownerCt chain. The last parent that was rendered and/or the top parent that is not yet rendered are good places to start debugging from to see why the expected layout did not occur. Layouts can get tricky especially if they're complex and nested.
Kevin
A: 

I know this thread is 2 months old, so I'm not sure if you ever found a solution. However, I just ran into the same thing and came across your thread while looking for an answer. This is what I ended up doing:

Where you're currently running panel.update(content), try this:

if(panel.rendered) panel.update(content);
else panel.contentToLoad = content;

Set up a listener for the render event to run:

if(this.contentToLoad) panel.update(this.contentToLoad);

That way, if the panel isn't rendered, it will store the content somewhere and the render listener will load whatever is there when the panel IS rendered.

Derek