缓冲网格和行扩展器插件一起在 extjs 中不起作用

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

要求:为 extjs(4.2.2) 网格提供无限滚动以及行扩展功能。

但是两个插件都不起作用, 行扩展器插件不允许数据加载到网格的缓冲存储中。

当 rowexpander 插件被注释时,无限滚动网格正在加载。

如何同时拥有这两个功能?

我通过扩展 extjs rowexpander 创建了一个 rowexpander 插件,如下所示, 在这里,如果我在下面的行中注释掉至少一个记录正在加载

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

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;
    }
});

当 getrowbodycontent 从 setCmp 中移除时,

在 setCmp 中调用 getrowbodycontent 时,

此解决方案使用 bufferedrendererrowexpander 插件。我不知道你是如何获取数据的,所以这个例子生成了一些假数据并动态加载数据。

希望对您有所帮助。

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();

});

备注:

已使用 ExtJS 4.2.1 和 Internet Explorer 11、Google Chrome 68、Mozilla Firefox 61、Microsoft Edge 42 进行测试。

Fiddle可以找到here.