Search code examples
extjspluginsinfinite-scrollextjs4.2rowexpansion

Buffered grid and row expander plugin together are not working in extjs


Requirement: To have infinite scrolling for a extjs(4.2.2) grid along with row expanding functionality.

But both the plugins together not working, row expander plugin not allowing data to load into buffered store of a grid.

when rowexpander plugin is commented, then infinite scroll grid is loading.

how to have both the functionalities?

i have created a rowexpander plugin as below by extending extjs rowexpander, here if i comment out below line thne atleast one rec is getting loaded

feature.getRowBodyContents = Ext.bind(me.getRowBodyContents, me);

Ext.define('Premier.view.tools.NM.Plugin.NotesGridRowExpander', {

    extend: 'Ext.grid.plugin.RowExpander',

    alias: 'plugin.notes-rowexpander',
    rowBodyTpl: [
        '<div class="notes-management-tool"> ',
        '<table cellspacing="0" cellpadding="0" class="notes-management-tool-table">',
            '<tr>',
                '<th valign="middle" class="notes-management-tool-table-date" style="color:black;width:130px;">Last Edited Date</th>',
                '<th valign="middle" class="notes-management-tool-table-note" style="color:black;width:360px;">Notes</th>',
                '<th valign="middle" class="notes-management-tool-table-editedBy" style="color:black;width:210px;">Last Edited By</th>',
                '<th valign="middle" class="notes-management-tool-table-actions" style="color:black;width:50px;">Actions</th>',
            '</tr>',
            '<tpl for=".">',
               '<tr>',
                    '<td valign="middle" class="notes-management-tool-table-date" style="color:black">{[(Ext.util.Format.date(Ext.Date.parse(values.LastEditedDate, "MS"), "M-d-Y h:i A"))|| "&nbsp;"]}</td>',
                    '<td valign="middle"class="notes-management-tool-table-note" style="color:black">{[(values.Note)|| "&nbsp;"]}</td>',
                    '<td valign="middle" class="notes-management-tool-table-editedBy" style="color:black">{[(values.LastEditedBy)|| "&nbsp;"]}</td>',
                    '<td valign="right" class="notes-management-tool-table-actions" ><div style="margin-left:3px" data-qtip="Edit"  class = "{[parent.AccountId == values.LastEditedById ?   "edit-notes-record-icon-active " : "edit-notes-record-icon-inactive "]}-noteId-{[this.getStringId(values.NoteId)]}-entityId-{[this.getStringId(values.EntityId)]}-entityTypeId-{[this.getStringId(values.EntityTypeId)]}"></div><div style="margin-left:3px" data-qtip="Delete"  class = "{[parent.AccountId == values.LastEditedById ?   "trash-icon " : "disabled-trash-icon " ]}-noteId-{[this.getStringId(values.NoteId)]}-entityId-{[this.getStringId(values.EntityId)]}-entityTypeId-{[this.getStringId(values.EntityTypeId)]}"></div></td>',
                '</tr>',
            '</tpl>',
        '</table>',
        '</div> ',
        {
            getStringId: function (id) {
                return id.toString();
            }
        }
    ],
    expandAllFlag: false,
    constructor: function () {
        var me = this;
        me.callParent(arguments);
    },

    setCmp: function (grid) {

        var me = this, features, i, feature;

        me.callParent(arguments);

        features = grid.features;

        for (i = 0; i < features.length; i++) {
            if ((feature = features[i]).ftype == 'rowbody') {
                break;
            }
        }
        if (feature) {
            //This function is abstracted as a private function kind of. So overriding the method to call
            //our own function
            feature.getRowBodyContents = Ext.bind(me.getRowBodyContents, me);
        }
    },

    getRowBodyContents: function (record) {
        var content = '', data;
        if(record.data) {
            data = record.data.NotesChildViews.sort(
                function (rec1, rec2) {
                    var a= Ext.Date.parse(rec1.LastEditedDate, "MS");
                    var b =Ext.Date.parse(rec2.LastEditedDate, "MS");
                    return a>b ? -1 : a<b ? 1 : 0;

                });
        }

        if (data) {
            data.AccountId = this.grid.app.getAccountId();
            content = this.rowBodyTpl.apply(data);
        }
        return content;
    },


    getHeaderConfig: function () {
        var me = this;

        return {
            itemId: 'rowExpanderHeader',
            width: 40,
            lockable: false,
            sortable: false,
            resizable: false,
            draggable: false,
            hideable: false,
            text: '<div class="notes-grid-expand"></div>',
            menuDisabled: true,
            tdCls: Ext.baseCSSPrefix + 'grid-cell-special',
            innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-row-expander',
            renderer: function (value, metadata) {
                // Only has to span 2 rows if it is not in a lockable grid.
                if (!me.grid.ownerLockable) {
                    metadata.tdAttr += ' rowspan="2"';
                }
                return '<div style="margin: 4px 0px 0px 8px;" class="' + Ext.baseCSSPrefix + 'grid-row-expander" role="presentation"></div>';
            },
            processEvent: function (type, view, cell, rowIndex, cellIndex, e, record) {
                if (type == "mousedown" && e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-expander')) {
                    me.toggleRow(rowIndex, record);
                    return me.selectRowOnExpand;
                }
            },
            listeners: {
                'afterrender': me.handleExpansion,
                scope: me
            }
        };
    },
    handleExpansion: function (headerObj) {
        var me = this;
        headerObj.el.on('click', function () {

            me.cmp.fireEvent('notes-grid-expansion');
        });    
    },
    updateHeaderText: function () {
        var me = this;
        if (me.expandAllFlag == false) {
            me.cmp.headerCt.down('#rowExpanderHeader').setText('<div class="notes-grid-collapse"></div>');
            me.expandAllFlag = true;
        }
        else {
            me.cmp.headerCt.down('#rowExpanderHeader').setText('<div class="notes-grid-expand"></div>');
            me.expandAllFlag = false;
        }
    },
    setDefaultHeader: function () {
        var me = this;
        me.cmp.headerCt.down('#rowExpanderHeader').setText('<div class="notes-grid-expand"></div>');
        me.expandAllFlag = false;
    }
});

when getrowbodycontent is removed from setCmp then , enter image description here

when calling getrowbodycontent in setCmp, enter image description here


Solution

  • This solution uses bufferedrenderer and rowexpander plugins. I don't know how you get data, so the example generates some fake data and loads data dynamically.

    I hope this helps.

    Ext.define('testmodel', {
        extend: 'Ext.data.Model',
        fields: [
            {name: 'name', type: 'string'},
            {name: 'index', type: 'number'}
        ]
    });
    
    
    Ext.define('Test.RowExpander', {
    
        extend: 'Ext.grid.plugin.RowExpander',
    
        rowBodyTpl: [
            "<tpl>",
            "<p>Item name: {name}</p>",
            "<p>Item index: {index}</p>",
            "</tpl>"
        ],
        expandAllFlag: false,   
    
        constructor: function() {
            this.callParent(arguments);
        },
    
        setCmp: function (grid) {
    
            var me = this, features, i, feature;
    
            me.callParent(arguments);
    
            features = grid.features;
    
            for (i = 0; i < features.length; i++) {
                if ((feature = features[i]).ftype == 'rowbody') {
                    break;
                }
            }
            if (feature) {
                feature.getRowBodyContents = Ext.bind(me.getRowBodyContents, me);
            }
        },
    
        getRowBodyContents: function (record) {
            var content = '', data;
            if (record.data) {
                data = record.data;
            }
            if (data) {
                content = this.rowBodyTpl.apply(data);
            }   
            return content;
        }
    
    });
    
    Ext.onReady(function() {
    
        Ext.define('Test.TestWindow', {
            extend: 'Ext.window.Window',
    
            closeAction: 'destroy',
            border: false,
            width: 560,
            height: 500,
            modal: true,
            closable: true,
            resizable: false,
            layout: 'fit',
    
            setStoreData: function() {
                var me = this;
    
                me.storeData = [];
                for (i = 1; i <= 15000; i++) {
                    me.storeData.push(
                        {"name": "Name"+i, "index": i}
                    );
                }
            },
    
            initComponent: function() {
                var me = this;
                me.callParent(arguments);
    
                me.setStoreData();
                me.store = Ext.create('Ext.data.Store', {
                    autoLoad: false,
                    pageSize: 16,
                    data: [],       
                    model: 'testmodel'
                });
    
                me.rowexpander = Ext.create('Test.RowExpander', {
    
                });
                me.bufferedrenderer = Ext.create('Ext.grid.plugin.BufferedRenderer', {
                });
    
                me.grid = Ext.create('Ext.grid.Panel', {
                    loadMask: true,
                    plugins: [
                        me.bufferedrenderer,
                        me.rowexpander
                    ],
                    selModel: {
                        pruneRemoved: false
                    },
                    stripeRows: true,
                    store: me.store,
                    columnLines: false,
                    columns : [
                        {header : 'Name', sortable : true, width: 100, dataIndex : 'name'},
                        {header : 'Index', sortable : true, width : 100, dataIndex : 'index'}
                    ]
                });
                me.add(me.grid);
    
                me.store.loadData(me.storeData);
            }
        }); 
    
        var win = new Test.TestWindow({
        });
        win.show();
    
    });
    

    Notes:

    Tested with ExtJS 4.2.1 and Internet Explorer 11, Google Chrome 68, Mozilla Firefox 61, Microsoft Edge 42.

    Fiddle can be found here.