olegtaranenko
olegtaranenko

Reputation: 3850

Extjs: Reuse the same grid in TabPanel

in a Extjs application I have a Grid and a Tabs line over it. Content of the Grid depends on the selected Tab. Say tabs has Jan-Feb-Mar-... values. Clicking of the Tab I would reload grid's store

Question: is it possible to avoid duplicating of the 12 grid components in favor to have one shared instance?

Thanks

Disclaimer: searching at the sencha's forum, google, stackoverflow was not successful :(

Upvotes: 3

Views: 4107

Answers (6)

mixo
mixo

Reputation: 329

For me good solution was to use a left toolbar called lbar with list of buttons and a single grid instead of tabpanel

Upvotes: 0

user2500262
user2500262

Reputation: 21

Try this

    var gridJanName = Ext.create('Ext.grid.Panel', {
        enableColumnHide: false,
        autoScroll:true,
        store: storeJanNameGroup,
        border:true,
        stripeRows: true,
        columnLines:false,
        loadMask: true,
        tbar:tbgridTools,
        margin: '1 1 1 1',
        pageSize: 100,
        maxWidth:700,
        features: [groupFeature],
        selModel: {
            mode: 'MULTI'
        },
        columns: [
            {xtype:'rownumberer',width:50},
            {dataIndex:'id', hidden:true},
        //etc
        ]
    }); 
        var gridFebName = Ext.create('Ext.grid.Panel', {
        enableColumnHide: false,
        autoScroll:true,
        store: storeJanNameGroup,
        border:true,
        stripeRows: true,
        columnLines:false,
        loadMask: true,
        tbar:tbgridTools,
        margin: '1 1 1 1',
        pageSize: 100,
        maxWidth:700,
        features: [groupFeature],
        selModel: {
            mode: 'MULTI'
        },
        columns: [
            {xtype:'rownumberer',width:50},
            {dataIndex:'id', hidden:true},
        //etc
        ]
    });
    //
    //etc grid
    //


    var JanPanel = Ext.create('Ext.panel.Panel', {
        title:'Jan',
        bodyPadding: 5, 
        Width:780,
        layout: {
            type: 'hbox',
            align: 'stretch'
        },
        items: [gridJanName]
    });
    var FebPanel = Ext.create('Ext.panel.Panel', {
        title:'Feb',
        bodyPadding: 5, 
        Width:780,
        layout: {
            type: 'hbox',
            align: 'stretch'
        }
        //,items: [gridFebName]
    });
    var MarPanel = Ext.create('Ext.panel.Panel', {
        title:'Mar',
        bodyPadding: 5, 
        Width:780,
        layout: {
            type: 'hbox',
            align: 'stretch'
        }
        //,items: [gridMarName]
    });
    //etc
    var eachMonthstabs = Ext.create('Ext.tab.Panel', {
        minTabWidth: 130,
        tabWidth:150,
        //Width:750,
        scroll:false,
        autoHeight: true,
        id:'timestabs',
        enableTabScroll:true,
        items: [
            {
                xtype:JanPanel
            },
            {
                xtype:FebPanel
            },
            {
                xtype:MarPanel
            }
            ///etc
            ]
    });

Upvotes: 0

CallMeLaNN
CallMeLaNN

Reputation: 8568

Since this is the only place discussed about this until now, I share what I just found.

The trick is use dockedItems in ExtJs 4 (Not sure either grid can be added into tbar in ExtJs 3) When changing the active tab, only body will be change but not the docked item. Just set the grid height equal to the body during boxready and resize so that we can't see the body anymore.

This is the code for ExtJs 4.2 MVC that also make use of refs.

Ext.define('app.controller.Notification', {
extend: 'Ext.app.Controller',
views: ['notification.List'],
stores: ['Notification'],
models: ['Notification'],

refs: [{
    ref: 'pnlNotif',
    selector: 'pnlNotif'
}, {
    ref: 'notifList',
    selector: 'notifList'
}],

init: function () {
    this.control({
        'dbPnlNotif': {
            added: this.pnlNotifAdded,
            boxready: this.calcNotifListSize,
            resize: this.calcNotifListSize,
            tabchange: this.pnlNotifTabChange
        }
    });
},

pnlNotifAdded: function (pnlNotif) {
    pnlNotif.add({ title: '1', html: '1' });
    pnlNotif.add({ title: '2', html: '2' });
    pnlNotif.add({ title: '3', html: '3' });
},

calcNotifListSize: function (pnlNotif) {
    // calc the notification list height to make sure it use the whole body
    // This way we can use only one instance of list to display for each tabs
    // because the list is rendered as dockedItems
    var height = pnlNotif.getHeight();
    var headerHeight = pnlNotif.getDockedItems()[0].getHeight();
    var tabBarHeight = pnlNotif.getDockedItems()[1].getHeight();
    height = height - headerHeight - tabBarHeight;
    if (this.getNotifList().getHeight() !== height) {
        this.getNotifList().setHeight(height - 1);// - 1 to include border bottom
    }
},

pnlNotifTabChange: function (pnlNotif, newTab) {
    // do something to filter the list based on selected tab.
}
});

Ext.define('ML.view.Notification', {
extend: 'Ext.tab.Panel',
alias: ['widget.pnlNotif'],
title: 'Notification',

dockedItems: [{
    xtype: 'notifList'
}]
});

Ext.define('ML.view.notification.List', {
extend: 'Ext.grid.Panel',
alias: 'widget.notifList',
dock: 'top',
store: 'Notification',

initComponent: function () {
    this.columns = [
        ...
    ];
    this.callParent(arguments);
}
});

Upvotes: 0

shivashankar
shivashankar

Reputation: 111

Hope the following implementation meet your needs 1. Create your custom grid and register it 2. place it tab panel

As the grid is created using xtype, it would not create 12 instances when you change tabs.

 Application.PersonnelGrid = Ext.extend(Ext.grid.GridPanel, {
         border:false
        ,initComponent:function() {
            Ext.apply(this, {
                 store:new Ext.data.Store({...})
                ,columns:[{...}, {...}]
                ,plugins:[...]
                ,viewConfig:{forceFit:true}
                ,tbar:[...]
                ,bbar:[...]
            });

            Application.PersonnelGrid.superclass.initComponent.apply(this, arguments);
        } // eo function initComponent

        ,onRender:function() {
            this.store.load();

            Application.PersonnelGrid.superclass.onRender.apply(this, arguments);
        } // eo function onRender
    });

    Ext.reg('personnelgrid', Application.PersonnelGrid);

    var panel = new Ext.TabPanel({
                    items:[{  
                            title:'Jan', 
                            items: [{xtype:'personnelgrid'}]
                          }, { 
                            title: 'Feb', 
                            items: [{xtype:'personnelgrid'}]
                          }
                          ....
                           {
                             title: 'Dec',
                             items: [{xtype:'personnelgrid'}] 
                           }] 
                  }) 

Upvotes: 0

Brian Moeskau
Brian Moeskau

Reputation: 20429

I haven't tried this myself, but I imagine that you could create a TabPanel with empty tabs and size the TabPanel so that only the tab strip is visible. Under that (using the appropriate layout, border, vbox, etc.) create your GridPanel and use the TabPanel's activate event to reload the grid based on the currently-active tab.

Upvotes: 0

Mchl
Mchl

Reputation: 62387

It is, but it would require more effort than it is worth. Just create a prototype for your component, so that you can create new instances really quickly.

Upvotes: 2

Related Questions