Search code examples
javascriptextjsextjs4.2extjs-grid

Ext JS: Add button to a column in a grid to show/hide other columns


I'm trying to create the effect of "expanding/collapsing" columns in an Ext JS grid. To do this, I'd like to add an icon/button next to the name of a column, such that when somebody clicks on it, it's child columns are either hidden or shown.

I've created a fiddle (code is also pasted below) which shows how I want my grid to behave: http://jsfiddle.net/a1umupea/

In my solution, I've created a link which calls a javascript function that manipulates the grid.

Is there a better way to achieve this using Ext JS 4.2, rather than writing a separate javascript function?

Ext.onReady(function () {
    Ext.create('Ext.data.Store', {
        storeId: 'fruitStore',
        fields: ['name', 'Total', 'Apple', 'Banana', 'Orange'],
        data: {
            'items': [{
                'name': 'Lisa',
                "Total": "5",
                "Apple": "3",
                "Banana": "1",
                "Orange": "1"
            }, {
                'name': 'Bart',
                "Total": "10",
                "Apple": "5",
                "Banana": "2",
                "Orange": "3"
            }, {
                'name': 'Homer',
                "Total": "15",
                "Apple": "5",
                "Banana": "5",
                "Orange": "5"
            }, {
                'name': 'Marge',
                "Total": "15",
                "Apple": "10",
                "Banana": "3",
                "Orange": "2"
            }]
        },
        proxy: {
            type: 'memory',
            reader: {
                type: 'json',
                root: 'items'
            }
        }
    });

    Ext.create('Ext.grid.Panel', {
        title: 'Fruits',
        id: 'fruitGrid',
        layout:'fit',
        store: Ext.data.StoreManager.lookup('fruitStore'),
        columns: [{
            text: 'Name',
            dataIndex: 'name'
        }, {
            text: '<a href="#" onclick="toggle(this)">[+]</a> Fruits',
            columns:[

            {
                    text: 'Total',
                    dataIndex: 'Total'
            },
            {
                text: 'Apple',
                dataIndex: 'Apple',
                hidden:true
            },
            {
                text: 'Banana',
                dataIndex: 'Banana',
                hidden:true
            },
            {
                text: 'Orange',
                dataIndex: 'Orange',
                hidden:true
            }
          ]
         }   
        ],
        height: 300,
        width: 500,
        renderTo: Ext.getBody()
    });
});


function toggle(t){
    var grid = Ext.getCmp('fruitGrid');
    console.log(grid);
    for(var i = 0 ; i < grid.headerCt.gridDataColumns.length ; i++){
        var col = grid.headerCt.gridDataColumns[i];

         if (col.text == 'Apple' || col.text=='Banana' || col.text=='Orange'){
            if(col.isVisible()) col.setVisible(false);
            else col.setVisible(true);
        }
    }
    if(t.text.indexOf('+') != -1){
            t.text=t.text.replace('+','-');
    }
    else
        t.text=t.text.replace('-','+');
}

Solution

  • Use the headerclick event with event delegation:

    Ext.onReady(function() {
        var s = Ext.create('Ext.data.Store', {
            fields: ['name', 'Total', 'Apple', 'Banana', 'Orange'],
            data: [{
                name: 'Lisa',
                Total: "5",
                Apple: "3",
                Banana: "1",
                Orange: "1"
            }, {
                name: 'Bart',
                Total: "10",
                Apple: "5",
                Banana: "2",
                Orange: "3"
            }, {
                name: 'Homer',
                Total: "15",
                Apple: "5",
                Banana: "5",
                Orange: "5"
            }, {
                name: 'Marge',
                Total: "15",
                Apple: "10",
                Banana: "3",
                Orange: "2"
            }]
        });
    
        var grid = Ext.create('Ext.grid.Panel', {
            title: 'Fruits',
            store: s,
            columns: [{
                    text: 'Name',
                    dataIndex: 'name'
                }, {
                    text: '<a class="expander">[+]</a> Fruits',
                    columns: [{
                        text: 'Total',
                        dataIndex: 'Total'
                    }, {
                        text: 'Apple',
                        dataIndex: 'Apple',
                        hidden: true
                    }, {
                        text: 'Banana',
                        dataIndex: 'Banana',
                        hidden: true
                    }, {
                        text: 'Orange',
                        dataIndex: 'Orange',
                        hidden: true
                    }]
                }
    
            ],
            height: 300,
            width: 500,
            renderTo: Ext.getBody(),
            listeners: {
                headerclick: function(headerCt, column, e) {
                    var cols, len, i, col, text;
                    if (e.getTarget('.expander')) {
                        e.stopEvent();
                        cols = headerCt.gridDataColumns;
                        for (i = 0, len = cols.length; i < len; i++) {
                            col = cols[i];
    
                            if (col.text == 'Apple' || col.text == 'Banana' || col.text == 'Orange') {
                                col.setVisible(col.hidden);
                            }
                        }
                        text = column.text;
                        if (text.indexOf('+') != -1) {
                            text = text.replace('+', '-');
                        } else {
                            text = text.replace('-', '+');
                        }
                        column.setText(text);
                    }
                }
            }
    
        });
    });