PDA

View Full Version : Adding / Removing panels from a window leaves old content



tomb@ibcos.co.uk
8 Mar 2011, 9:05 AM
Hi Guys,

I have a basic Ext window (win1) which I add a child panel (child1) to. Once added, I remove the child1 without destroying it and add a second panel (child2), then update win1 calling doLayout. The problem is the child1 stays visible inside win1 underneath child2. If the window is resized at all child1 is not updated and if you examine the items mixed collection of win1 you can see only child2. So child1 has been removed from win1 but is still being drawn.

Any ideas on how to fix?

Thanks


win1 = new Ext.Window({
width:300,
height:300,
title:'Add / Remove Test'
})
win1.show();

child1 = new Ext.Panel({title:'child1', height:100})
child2 = new Ext.Panel({title:'child2', height:100})

win1.add(child1);
win1.doLayout()

win1.remove(child1, false);
win1.add(child2);
win1.doLayout()

tomb@ibcos.co.uk
9 Mar 2011, 2:29 AM
Ok, I've tracked this down to the fact that when a panel is removed from its container, the panels el is left in the DOM. A doLayout doesn't remove the invalidated el because the child panel has been removed from its containers items array.

so, I added a listener to my child panels that listens for the remove event. When the panel is removed it now removes its offending el from the container. Some of the below code is taken from the destroy method. I noticed that if you destroy the child, the child's el is removed immediately.

Obviously I don't want to add a removed listener to every panel, so my thinking is I might be able to add an override to the Ext.Panel class to clean up the el on a remove.

Is this the best thing to do?

Also, is this a known bug? I can't find anyone else having the issue.


removed : function(c, ownerCt) {
if(c.rendered){
c.el.remove();
if(c.actionMode == 'container' || c.removeMode == 'container'){
c.container.remove();
}
c.rendered = false;
delete c.tools;
delete c.el;
}
}

tomb@ibcos.co.uk
9 Mar 2011, 2:40 AM
Ok, so I could use a card layout and do a getLayout().setActiveItem() to achieve the swapping of panels.


But, surely the panel el remove bug still exists? Or is this expected behavior?

brittongr
9 Mar 2011, 11:13 PM
This is what i'm doing right now with the same scenario and this works well for me... i put the code bellow according to your variables.



//This part is the same...
win1.add(child1);
win1.doLayout();

//Before removing child1 i call hide function
child1.hide();

win1.remove(child1, false);

//In my case child2 could be already created at this point and i just make sure it will be visible child2.show(); //Maybe you don't need this line.

win1.add(child2);

win1.doLayout();

tomb@ibcos.co.uk
10 Mar 2011, 1:14 AM
Hi brittongr,

Thanks for your reply. Hiding the panel does indeed get around the issue. However, it introduces another problem. When you hide a panel the panel still exists in the window's items array and the el is still in the DOM. If a fit layout is used on the window the second panel doesn't size correctly.


win1 = new Ext.Window({
width:300,
height:300,
title:'Add / Remove Test',
layout:'fit'
}).show()
child1 = new Ext.Panel({title:'child1'})
child2 = new Ext.Panel({title:'child2'})
win1.add(child1)
child1.hide()
win1.add(child2)
win1.doLayout()


In the docs, the remove method clearly states "Removes a component from this container." Should this not be reflected in the DOM?

Thanks

brittongr
10 Mar 2011, 1:47 AM
You must remove it from its container, i can see you removed this line:
win1.remove(child1, false);

You must keepit in order to remove the panel but not destroying it so then you can use it.
I test it with this:



var win;
if (!win)
{
win = new Ext.Window(
{
layout: 'fit',
width: 500,
height: 300,
closeAction: 'hide'
});
}

win.show(this);

var child1 = new Ext.Panel(
{
title: 'child1',
items: new Ext.form.TextField()
});

var child2 = new Ext.Panel(
{
title: 'child2',
html:'Some text'
});

win.add(child1);
child1.hide();
win.remove(child1, false);

win.add(child2);
win.doLayout();

alert(child1.title);
});

tomb@ibcos.co.uk
10 Mar 2011, 4:12 AM
I see... Ok, so in order to swap out a panel for another panel you need to tell child1 to remove and hide and child2 to add and show.

This code for performing this can be shortened a little to this.


win.remove(child1, false).hide();
win.add(child2).show();


But am I wrong in thinking this is still more code than should be required to perform a really simple task? IMHO, the add and remove methods of Ext.Container should perform the doLayout automatically along with updating the DOM on the remove to actually remove the el. Both add and remove methods should accept an array of components to keep performance up.

Also, there seems to be some confusion with the doLayout method. The documentation for doLayout says "Force this container's layout to be recalculated. A call to this function is required after adding a new component to an already rendered container, or possibly after changing sizing/position properties of child components."

This is not entirely true. I can add a child to a window and call doLayout. I can then remove the child (which doesn't alter the DOM), add the child to a second window (which still doesn't alter the DOM), move the child back to the original window and use it without having to call doLayout. Throughout moving the child around, I can show and hide it which will always show it inside the first window.

Maybe I'm being picky but the method names and descriptions seem to suggest one thing and do another.

brittongr
10 Mar 2011, 4:42 AM
You can start a thread about this in the Communit Discussion Forum (http://www.sencha.com/forum/forumdisplay.php?68-Community-Discussion) or Ext Open Discussion (http://www.sencha.com/forum/forumdisplay.php?6-Ext-Open-Discussion) to suggest that.