缓冲网格和行扩展器插件一起在 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"))|| " "]}</td>',
'<td valign="middle"class="notes-management-tool-table-note" style="color:black">{[(values.Note)|| " "]}</td>',
'<td valign="middle" class="notes-management-tool-table-editedBy" style="color:black">{[(values.LastEditedBy)|| " "]}</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 时,
此解决方案使用 bufferedrenderer
和 rowexpander
插件。我不知道你是如何获取数据的,所以这个例子生成了一些假数据并动态加载数据。
希望对您有所帮助。
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.
要求:为 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"))|| " "]}</td>',
'<td valign="middle"class="notes-management-tool-table-note" style="color:black">{[(values.Note)|| " "]}</td>',
'<td valign="middle" class="notes-management-tool-table-editedBy" style="color:black">{[(values.LastEditedBy)|| " "]}</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 时,
此解决方案使用 bufferedrenderer
和 rowexpander
插件。我不知道你是如何获取数据的,所以这个例子生成了一些假数据并动态加载数据。
希望对您有所帮助。
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.