Create custom layout or config like accordion which will make all panels collapsible

411 Views Asked by At

I am using Extjs 6.5.3.

I want to create custom layout or a config, so that when I use that in my file all the panels will become collapsible.

I know ExtJS has Accordion layout by using which we can make all panels collapsible but accordion layout is having issue for multiple panels open at the same time even we add multi: true config for the same. It will not allow to expand and close multiple panels at the same time.

Below is the example of not allowing multiple panels to open at same time even added multi:true

Ext.create('Ext.panel.Panel', {
    title: 'Accordion Layout',
    width: 300,
    height: 300,
    defaults: {
        // applied to each contained panel
        bodyStyle: 'padding:15px'
    },
    layout: {
        // layout-specific configs go here
        type: 'accordion',
        titleCollapse: false,
        animate: true,
        multi: true,
        activeOnTop: true
    },
    items: [{
        title: 'Panel 1',
        html: 'Panel content!'
    }, {
        title: 'Panel 2',
        html: 'Panel content!'
    }, {
        title: 'Panel 3',
        html: 'Panel content!'
    }],
    renderTo: Ext.getBody()
});

I also know that by using vbox layout we can make panels collapsible like below

Ext.create('Ext.panel.Panel', {
    title: 'Accordion Layout',
    width: 300,
    height: 300,
    defaults: {
        // applied to each contained panel
        bodyStyle: 'padding:15px',
        collapsible: true
    },
    layout: {
        // layout-specific configs go here
        type: 'vbox'
    },
    items: [{
        title: 'Panel 1',
        html: 'Panel content!'
    }, {
        title: 'Panel 2',
        html: 'Panel content!'
    }, {
        title: 'Panel 3',
        html: 'Panel content!'
    }],
    renderTo: Ext.getBody()
});

But I want to have it as config or custom layout, so that I can reuse it in any place. To do this I am not finding any way.

1

There are 1 best solutions below

1
On

For this you can easily implement using Accordion layout. You need to override accordion layout onBeforeComponentCollapse method by using Ext.override.

In source file exiting onBeforeComponentCollapse method they taking next() or prev() to expanding at-least one component. You just need to add one custom config atleastOneExpanded:false like this

layout: {
    type: 'accordion',
    multi: true,
    atleastOneExpanded: false
}

And in Ext.override you need check this condition

Ext.override(Ext.layout.container.Accordion, {
     onBeforeComponentCollapse: function(comp) {
         var me = this,
             owner = me.owner,
             toExpand,
             expanded,
             previousValue;

         if (me.owner.items.getCount() === 1) {
             // do not allow collapse if there is only one item
             return false;
         }

         if (!me.processing) {
             me.processing = true;
             previousValue = owner.deferLayouts;
             owner.deferLayouts = true;
             toExpand = comp.next() || comp.prev();

             //IF atleastOneExpanded config is true then one panel will always expand.
             if (me.atleastOneExpanded) {
                 // If we are allowing multi, and the "toCollapse" component is NOT the only expanded Component,
                 // then ask the box layout to collapse it to its header.
                 if (me.multi) {
                     expanded = me.getExpanded();

                     // If the collapsing Panel is the only expanded one, expand the following Component.
                     // All this is handling fill: true, so there must be at least one expanded,
                     if (expanded.length === 1) {
                         toExpand.expand();
                     }

                 } else if (toExpand) {
                     toExpand.expand();
                 }
             }
             owner.deferLayouts = previousValue;
             me.processing = false;
         }
     }
 });

FIDDLE

In above fiddle I have created a demo using Ext.override.

CODE SNIPPET

Ext.application({
    name: 'Fiddle',

    launch: function() {

        Ext.create('Ext.panel.Panel', {
            title: 'Accordion Layout',

            defaults: {
                bodyStyle: 'padding:15px'
            },

            layout: {
                type: 'accordion',
                multi: true,
                atleastOneExpanded: false
            },

            items: [{
                title: 'Panel 1',
                html: 'Panel content!'
            }, {
                title: 'Panel 2',
                html: 'Panel content!'
            }, {
                title: 'Panel 3',
                html: 'Panel content!'
            }],

            renderTo: Ext.getBody()
        });
    }
});