Question

Concept: Consider having two panels A and B, and a window C like in the following example. The buttons on the window switches between the two panels.

var A = new Ext.Panel({
    title: 'A'
});

var B = new Ext.Panel({
    title: 'B'
});

var C = new Ext.Window({
    layout: 'fit',
    width: 300,
    height: 300,
    items: A,
    buttons: [
    {
        text: 'Switch to A',
        handler: function() {
            C.removeAll(false);
            C.add(A);
            C.doLayout();
        }
    }, {
        text: 'Switch to B',
        handler: function() {
            C.removeAll(false);
            C.add(B);
            C.doLayout();
        }
    }]
});
C.show();

The concept is very simple: Add a component, remove it and add the same instance again.

Problem: The switch from A to B works, but going back to A doesn't (B stays and A is not shown again).

Question: Thinking OOP, I would expect the above concept to work. Since this is not the case and its a very basic manouvre, how should I think / contemplate / design when I'm trying to do this?

I understand that there might be varying cases when considering a FormPanel vs. other layouts/components - but there must be a general and correct way to do this :)

Was it helpful?

Solution

Perhaps a card layout is exactly what you need:

var C = new Ext.Window({
    layout: 'card',
    width: 300,
    height: 300,
    activeItem: 0,
    items: [A, B],
    buttons: [{
        text: 'Switch to A',
        handler: function() {
            C.getLayout().setActiveItem(0);
        }
    }, {
        text: 'Switch to B',
        handler: function() {
            C.getLayout().setActiveItem(1);
        }
    }]
});
C.show();

I assume the problem with your code is that you're reusing the same instance again. Ext internally sets a rendered-flag on a component once it has been written to the DOM tree. As the rendered flag is still true after you removed the component from C it won't be redrawn when you add the component again.

A simple modification will make your code work: add A.rendered = false; and B.rendered = false respectively before you call C.doLayout() in your button handlers.

But still the card-layout approach would be best-practice.

OTHER TIPS

I've found a simple solution, but it's more of a hack. After removing the component (your A or B panel), you have to add it to another container which must to be rendered. Here is an example in which the panels get moved to a hidden container:

var A = new Ext.Panel({
    title: 'A'
});

var B = new Ext.Panel({
    title: 'B'
});

var C = new Ext.Window({
    layout: 'fit',
    width: 300,
    height: 300,
    items: A,
    buttons: [
    {
        text: 'Switch to A',
        handler: function() {
            C.remove(B, false);
            T.add(B);
            C.add(A);
            C.doLayout();
        }
    }, {
        text: 'Switch to B',
        handler: function() {
            C.remove(A, false);
            T.add(A);
            C.add(B);
            C.doLayout();
        }
    }]
});

var T = new Ext.Container({
    renderTo: "temporaryContainer",
    renderHidden: true
});

C.show();

And somewhere in the page's body you need to have this:

<div id="temporaryContainer" class="x-hidden"></div>

Tested with ExtJs 4.0.2a.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top